代码之家  ›  专栏  ›  技术社区  ›  Rwky

在Git中进行“临时”提交的最佳方法是什么?

  •  18
  • Rwky  · 技术社区  · 14 年前

    假设我有一个有两个分支master和dev的项目,我有一堆dev的提交,用于一个特殊事件,这个事件一旦测试就合并到master中。然后在事件结束后,我想删除特定于事件的代码。但是,由于添加了事件代码之后已经进行了其他提交,因此Git重置将不起作用。

    当前,我使用git checkout从合并事件之前签出文件,然后使用git diff重新添加自事件提交以来所做的更改。在我看来,这是一个非常混乱的方法。

    对于在项目中使用临时代码,有人有更好的解决方案吗?

    编辑: 要清楚,更改需要提交、推送、未提交、推送。

    7 回复  |  直到 8 年前
        1
  •  17
  •   rfunduk    14 年前

    获取master并创建分支: git checkout -b special-event ,进行/应用更改。一旦事件结束,只需切换回master并放弃/删除分支。

    为了继续进行更改,请在master上进行更改,并在执行时将其合并到特殊分支中。 git checkout master …进行更改… git checkout special-event; git merge master .

    或者,在一次提交中进行所有与事件相关的特殊更改,然后使用 git revert 当您想要将它们展开并只指定该提交时。

        2
  •  2
  •   user1654465    12 年前

    “临时代码”?在Git中,我们使用分支。在Git中提交是非常轻量的,与其他系统相比,分支只是带有少量逻辑连接的提交的名称(或引用)是非常轻量的。

    逻辑的一小部分就是引用会自动更新到最后一次提交。这几乎就是分支的全部。这意味着在Git中创建和销毁分支是快速、简单甚至安全的,因为没有真正创建或删除任何分支。删除之后,您仍然可以通过提交ID引用分支头(是的,在它被垃圾收集之前,它仍然存在,甚至只有在没有其他引用的情况下才会发生这种情况)。

    几乎Git中的每个命令都将对提交的引用作为参数。对于Git合并也是如此。您不是在合并分支,而是在合并提交。是的,您键入“git merge”,但同样,分支只是提交的名称。只不过如此。既然您只需要将事件的提交分组在一起,就给它们一个名称。

    所以正确的做法是为事件创建一个分支。或者可能是两个:“事件主机”和“事件开发”。现在,在“event dev”中为事件开发代码。如果你遇到了一个需要在主代码中修复的bug,隐藏并切换到正常的“dev”分支,编写修复代码并提交。切换回“event dev”,从“dev”合并,然后弹出stash。继续开发,一旦完成,提交和测试。如果可以,将“event dev”合并为“event master”。这也将包含修复。请注意,修复程序尚不在“master”中。

    如果您需要将修复合并到“master”中,您只需按常规方式进行,因为修复位于“dev”中。

    基本上,在此设置中,您可以:

    • 像往常一样开发主代码:提交到“dev”,测试,并合并到“master”中;

    • 以类似的方式开发特定于事件的代码:您提交到“事件开发”,测试,并合并到“事件主机”;它只是相同的工作流;

    • 混合两个工作流;提交和切换分支,或使用git stash;

    • 自由合并分支(几乎);如果master被更新,并且需要对事件进行更改,则可以将master合并为event dev;如果您非常需要对事件进行更改,并且无法等待将它们推入master的常规测试周期,则可以将dev合并为event dev。只要合并是干净的,Git就会这样做,也就是说,除非在两个dev分支中以两种不同的方式更改同一段代码(这当然是需要处理的特殊情况);

    如果您需要额外的灵活性,请创建更多的分支。对于超级灵活性,您可以选择将单个提交提交提交到分支中,但一般来说,我建议不要这样做(只有当您真正知道自己在做什么时才这样做)。

    最后,我应该指出这个工作流程在Git中是很自然的。实际上,“开发”中的开发和“主控”中的拉式变更甚至不是最好的概括。习惯上,为正在开发的每个特性或模块创建一个开发分支,并将这些分支合并到“dev”中。

    我认为使用Git的正确心态是:“我今天想编写什么代码?功能X。好的,我们创建分支“功能X”并开始黑客攻击。你的那件事也没什么不同。

    现在,我知道我要告诉你的是,你应该从一开始就做些什么,而这对现在没有多大帮助。你需要修复你的树,因为-看起来-你对事件的更改与对“dev”分支的正常更改混合在一起。因此,您的问题是如何正确地创建“event dev”,只包含对事件所做的更改,并同时将它们从“dev”中删除。

    是时候重写历史了。这将是多么困难,这取决于变化的性质。例如,如果所有的更改都属于一个目录,那么事情就更容易了。

    以下是我将要做的(没有更好的了解):

    • 用git日志检查历史;

    • 找到第一个特定事件更改之前的提交,注意它的提交ID:这是'day-0'提交;

    • 创建一个名为“newdev”的分支,指向该提交。在干净的树中执行此操作,即在执行此操作之前提交:git checkout<commit id>-b newdev;

    • 创建“event dev”:git checkout-b event dev;

    • 现在有两个分支都指向“day-0”提交;

    • 现在再次查看历史记录(GitLogDev),您需要通过提交来跟踪它;

    • 我假设“day-0”之后的每个提交要么是属于主代码的提交,要么只是属于事件的提交。你要做的是在正确的分支中选择它们,如果是主代码,则选择“newdev”,如果是事件代码,则选择“event dev”;按照正确的顺序(从“day-0”到今天)一次选择一个;

    • 如果你很幸运,没有一个提交最终在“newdev”取决于“event dev”和“viceversa”中的提交;你有点完成了;你可能想重命名(保留它们)当前的主设备和dev以主控old和dev old,然后将newdev重命名为dev,从dev创建master,从event dev创建event master,然后设置好了;

    • 如果你运气不太好,有时你必须将“newdev”合并到“event dev”,因为有些提交取决于主代码中所做的更改,这很好,tho;如果你在这里感到有胆量,现在是时候阅读关于git-rebase的内容了;但是,除非你必须这样做,否则rebase不会。

    • 或者(更糟)“newdev”中的某些提交取决于“event dev”中的更改…糟糕的是,如果主分支需要的话,这个特定于事件的代码并不是特定于事件的。需要一些合并;

    • 或者(坏)一个提交包含两种更改:分而治之(您需要将更改分开并应用到正确的分支),这意味着您将提交分为两部分;

    • 或者其他一些我现在无法想象的事情,因为我没有足够的关于你的树的细节。

    可能是微风,也可能是噩梦。预先检查每个提交(git-show,你可以把它看作一个补丁),决定要做什么(最终不要选择cherry-pick,只编辑文件会更容易),如果不确定-猜猜-创建一个分支,在那里工作,看会发生什么,合并它如果高兴,放弃它,然后再试一次。

    到目前为止,我还没有提到它,但是当然,您可以复制整个树,包括git文件,并且在副本上工作是100%安全的。

    从一开始就做好是相当容易的。现在修好,好吧,祝你好运。:)

        3
  •  1
  •   dgnorton    14 年前

    git checkout -b event

    …进行特定事件更改…

    git commit -am "specific event change"

    …更改另一个特定事件…

    git commit -am "another specific event change"

    在这一点上, 主人 分支仍然完整,事件特定的更改位于 事件 分支机构。如果在 事件 使用分支 重碱

    git rebase master

    另一个答案建议合并 主人 进入之内 事件 但是 重碱 通常是更好的方法。一 重碱 剥离主题分支上的提交,提取更新的 主人 转发然后在顶部重新应用主题分支更改…就像主题分支更改是对最新版本的master所做的一样。

    在您的场景中,当事件结束时,只需删除 事件 分支机构。

        4
  •  1
  •   Dan Rosenstark    13 年前

    按照我的非专利方法汇总您的承诺:

    # work on a new branch
    git checkout -b event-36
    git commit -a -m "all broken dammit"
    git commit -a -m "fixed that damn code"
    git commit -a -m "almost ready, going to eat lunch"
    git commit -a -m "It's done!"
    
    # other people might be working on master in the meantime, so
    git checkout master
    git checkout -b erasemeImmediately
    git merge event-36
    git reset --soft master # THE KEY TO THE WHOLE THING: SOFT RESET!
    git commit -a -m "Event 36, all code in one commit"
    
    git checkout master
    git merge erasemeImmediately
    

    你可以用 reflog 但是你需要一个最新的计算机科学学位(也就是说,很难理解)。

    现在你的承诺是一个单一的。现在,您可以使用revert或执行cherry-pick来选择一个没有它的分支。

        5
  •  0
  •   cmcginty    14 年前

    GIT回复

    它将删除您需要撤消的任何提交或提交范围。推动公开回购也是安全的。

        6
  •  0
  •   pragman    8 年前

    根据我的经验,有些特殊事件有一种反复发生的方式。因此,这里要考虑的另一个解决方案是创建一个配置选项来支持处理特殊事件,以便在需要时打开和关闭它。

        7
  •  -1
  •   Splashdust    14 年前

    我相信 stash 做你想做的。