如何在过去的两个任意提交之间注入提交?

时间:2015-08-31 15:48:46

标签: git

假设我在仅限本地的分支上有以下提交历史记录:

A -- B -- C

如何在AB之间插入新的提交?

6 个答案:

答案 0 :(得分:108)

这比OP的答案更容易。

  1. git rebase -i <any earlier commit>。这将在您配置的文本编辑器中显示提交列表。
  2. 找到您想要插入的提交(让我们假设它是a1b2c3d)。在您的编辑器中,针对该行,将pick更改为edit
  3. 关闭文本编辑器(保存更改)以开始rebase。这使您在命令提示符处显示您之前选择的提交(a1b2c3d,就好像它刚刚提交了
  4. 进行更改并git commit修改,与大多数edit不同)。这会在您选择的之后创建一个新的提交
  5. git rebase --continue。这将重放连续的提交,将新的提交插入正确的位置。
  6. 请注意,这将重写历史记录,并打破任何试图拉动的人。

答案 1 :(得分:17)

结果很简单,答案是here。假设你在一个分支branch上。执行以下步骤:

  • 在您想要插入新提交之后从提交中创建临时分支(在本例中为commit A):

    git checkout -b temp A
    
  • 执行更改并提交它们,创建提交,让我们称之为N

    git commit -a -m "Message"
    

    (或git add后跟git commit

  • 将新提交后的提交(在这种情况下,将BC提交到新提交)重新绑定:

    git rebase temp branch
    

(可能您需要使用-p来保留合并,如果有的话 - 感谢a no longer existing comment ciekawy}

  • 删除临时分支:

    git branch -d temp
    

此后,历史记录如下:

A -- N -- B -- C

当然,在变基时可能会出现一些冲突。

如果您的分支机构不是本地分支,则会引入重写历史记录,因此可能会导致严重问题。

答案 2 :(得分:10)

假设提交历史记录为preA -- A -- B -- C,如果要在AB之间插入提交,则步骤如下:

  1. git rebase -i hash-of-preA

  2. Git会打开你的编辑器。内容可能是这样的:

    pick 8668d21 A
    pick 650f1fc B
    pick 74096b9 C
    

    将第一个pick更改为edit

    edit 8668d21 A
    pick 650f1fc B
    pick 74096b9 C
    

    保存并退出。

  3. 修改您的代码,然后git add . && git commit -m "I"

  4. git rebase --continue

  5. 现在您的Git提交历史记录为preA -- A -- I -- B -- C

    如果遇到冲突,Git将停止此提交。您可以使用git diff找到冲突标记并解决它们。解决所有冲突后,您需要使用git add <filename>告诉Git冲突已解决,然后重新运行git rebase --continue

    如果要撤消变基,请使用git rebase --abort

答案 3 :(得分:10)

更简单的解决方案:

  1. 最后创建新的提交,D。现在你有:

    A -- B -- C -- D
    
  2. 然后运行:

    $ git rebase -i hash-of-A
    
  3. Git将打开您的编辑器,它将如下所示:

    pick 8668d21 B
    pick 650f1fc C
    pick 74096b9 D
    
  4. 将D移动到顶部,然后保存并退出

    pick 74096b9 D
    pick 8668d21 B
    pick 650f1fc C
    
  5. 现在你将拥有:

    A -- D -- B -- C
    

答案 4 :(得分:4)

这是一种避免在我读过的其他答案中看到的改编过程中进行“编辑修改”的策略。

通过使用git rebase -i,可以获得自该提交以来的提交列表。 只需在文件顶部添加一个“ break”,这将导致重新设置在那时中断。

break
pick <B's hash> <B's commit message>
pick <C's hash> <C's commit message>

一旦启动,git rebase现在将在“中断”点停止。 现在,您可以编辑文件并正常创建提交。 然后,您可以使用git rebase --continue继续进行变基。这可能会导致您必须解决的冲突。如果您迷路了,别忘了您可以随时使用git rebase --abort中止。

这种策略可以推广到在任何位置插入提交,只需将“ break”放在要插入提交的位置即可。

重写历史记录后,请不要忘记git push -f。通常会出现有关其他人提取您的分支机构的警告。

答案 5 :(得分:3)

这里已经有很多好的答案。我只想通过4个步骤添加一个“无基准”解决方案。

此解决方案的一个优势是,您直到最后一步都不会碰到分支,因为当您100%确定最终结果是正确的时,您就可以方便的“预确认”步骤,可以进行AB测试


初始状态(我假设您的分支机构名称为master

A -- B -- C <<< master <<< HEAD

1)首先将HEAD指向正确的位置

git checkout A

     B -- C <<< master
    /
   A  <<< detached HEAD

(可选地,我们可以不使用HEAD来分离HEAD,而可以使用git checkout -b temp A创建一个临时分支,需要在过程结束时将其删除。这两种变体都可以正常工作,您可以按照自己的意愿进行操作,因为其他所有操作保持不变)


2)创建要插入的新提交D

# at this point, make the changes you wanted to insert between A and B, then

git commit -am "Message for commit D"

     B -- C <<< master
    /
   A -- D <<< detached HEAD (or <<< temp <<< HEAD)

3)然后带上最后丢失的提交B和C (如果还有更多提交,将在同一行)

git cherry-pick A..C

# (if any, resolve any potential conflicts between D and these last commits)

     B -- C <<< master
    /
   A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)

(如果需要,可以在此处进行舒适的AB测试)

现在是检查代码,测试需要测试的所有内容的时候了,您还可以比较/比较/检查所拥有的所得到的手术后。


4)取决于您在CC'之间进行的测试,可以还是可以。

(EITHER) 4-OK)最后,移动master的引用

git branch -f master HEAD

     B -- C <<< (B and C are candidates for garbage collection)
    /
   A -- D -- B' -- C' <<< master

(OR) 4-KO)保持master不变

如果您创建了一个临时分支,只需使用git branch -d <name>将其删除,但是如果您使用了分离的HEAD路由,则此时根本不需要执行任何操作,那么新提交将在之后立即进行垃圾回收您将HEAD重新连接到git checkout master

在这两种情况下(正常或正常),此时只需再次签出master即可重新附加HEAD