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

Bar*_*zKP 101 git

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

A -- B -- C
Run Code Online (Sandbox Code Playgroud)

如何在A和之间插入新的提交B

SLa*_*aks 141

它比OP的答案更容易.

  1. git rebase -i <any earlier commit>.这将在您配置的文本编辑器中显示提交列表.
  2. 找到你想要插入的提交(让我们假设它a1b2c3d).在您的编辑器中,对于该行,请更改pickedit.
  3. 通过关闭文本编辑器开始rebase(保存更改).这使您在命令提示符下使用您之前选择的提交(a1b2c3d),就像它刚刚提交一样.
  4. 进行更改和git commit(不要修改,与大多数edits 不同).这会您选择的提交之后创建新的提交.
  5. git rebase --continue.这将重放连续提交,将新提交插入正确的位置.

请注意,这将重写历史记录,并打破任何试图拉动的人.

  • 这在提交之后添加了新的提交,即在我要变基的提交(也是最后一次提交)之后,而不是在我要变基的提交之后。结果就像我只是在最后做了一个新的提交,并添加了我想要插入的更改。我的历史变成了“A -- B -- C -- D”,而不是期望的“A -- D -- B -- C”。 (3认同)
  • 现在`D`可以在任何地方提交.假设我们有'A - B - C`并且我们有一些提交`D`甚至不在这个分支中.我们知道它的SHA,我们可以做`git rebase -i HEAD~3`.现在在`A`和`B``pick`行之间,我们插入一个**新的**`pick`行,表示"选择SHA",给出所需`D`的哈希值.它不一定是完整的哈希,只是缩短的哈希.**`git rebase -i`只是挑选缓冲区中`pick`行列出的任何提交; 它们不一定是它为您列出的原始产品.** (3认同)
  • 甚至更容易,您可以在编辑器中的两次提交之间在其自己的行中使用`break`关键字(或在第一行中,在指定的提交之前插入一个提交)。 (3认同)
  • @XedinUnknown:然后您没有正确使用Rebase。 (2认同)
  • 要使用此答案,首先您必须确定新提交。在一种情况下,这可能只是最重要的;我们称之为“D”,所以我们有“A - B - C - D”,目标是“A - D - B - C”。`git rebase -i HEAD~4`,并在编辑器中将提交重新排序为 ADBC 顺序,保存,退出。 (2认同)

Bar*_*zKP 21

结果很简单,答案在这里找到.假设你在一个分支上branch.执行以下步骤:

(可能你需要使用-p保存合并,如果有任何-感谢一个不再存在的意见通过ciekawy)

在此之后,历史看起来如下:

A -- N -- B -- C
Run Code Online (Sandbox Code Playgroud)

当然,在重新定位时可能会出现一些冲突.

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

  • 当使用 -Xtheirs 选项使用 rebase 时,会自动正确解决冲突,因此 `git rebase tempbranch -Xtheirs`。注入脚本的有用答案! (3认同)
  • 我无法遵循SLaks接受的答案,但这对我有用。在获得所需的提交历史记录后,我必须使用git push --force来更改远程仓库。 (2认同)

Mat*_*hew 14

更简单的解决方案

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

    A -- B -- C -- D
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后运行:

    $ git rebase -i hash-of-A
    
    Run Code Online (Sandbox Code Playgroud)
  3. Git会打开你的编辑器,它看起来像这样:

    pick 8668d21 B
    pick 650f1fc C
    pick 74096b9 D
    
    Run Code Online (Sandbox Code Playgroud)
  4. 只需将D移动到顶部,然后保存并退出

    pick 74096b9 D
    pick 8668d21 B
    pick 650f1fc C
    
    Run Code Online (Sandbox Code Playgroud)
  5. 现在你将拥有:

    A -- D -- B -- C
    
    Run Code Online (Sandbox Code Playgroud)

  • 不错的想法,但是当你打算将这些变化变为wrt时,可能很难在C上引入D.到A. (5认同)
  • 我遇到的情况是,我有 3 个提交,我想将它们一起变基,而中间有一个不相关的提交。能够将提交提前或推迟到提交行中,这是非常好的。 (2认同)

Rom*_*eri 13

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


概括

git checkout A
# <<< modify your files at this point
git commit -am "Message for commit D"
git cherry-pick A..C
git branch -f master HEAD
Run Code Online (Sandbox Code Playgroud)

解释

(注意:这个解决方案的一个优点是直到最后一步你才接触你的分支,当你 100% 确定你对最终结果没问题时,所以你有一个非常方便的“预确认”步骤允许进行 AB 测试。)


初始状态(我假设master您的分支名称)

A -- B -- C <<< master <<< HEAD
Run Code Online (Sandbox Code Playgroud)

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

git checkout A

     B -- C <<< master
    /
   A  <<< detached HEAD
Run Code Online (Sandbox Code Playgroud)

(在这里,我们可以选择创建一个临时分支,而不是分离 HEAD,我们git checkout -b temp A需要在过程结束时将其删除。两种变体都可以工作,按照您的喜好进行,因为其他一切都保持不变)


2)创建要插入的新commit 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)
Run Code Online (Sandbox Code Playgroud)

3)然后带上最后丢失的提交 B 和 C 的副本(即使中间有更多提交,命令也是相同的,因为这是选择一系列提交)

git cherry-pick A..C

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

     B -- C <<< master
    /
   A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)
Run Code Online (Sandbox Code Playgroud)

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

现在是检查你的代码,测试任何需要测试的那一刻,你也可以比较/比较/检查你有什么你会得到什么样的操作后,只需通过交替检查CC'


4)取决于您在C和之间的测试C',它是 OK 还是 KO。

(EITHER) 4-OK) 最后,移动 refmaster

git branch -f master HEAD

     B -- C <<< (B and C are candidates for garbage collection)
    /
   A -- D -- B' -- C' <<< master
Run Code Online (Sandbox Code Playgroud)

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

如果你创建了一个临时党支部,只是删除它git branch -d <name>,但如果你去了分离的头路线,没有在所有的在这一点上需要采取行动,新的提交将符合垃圾收集你重新刚过HEADgit checkout master

在这两种情况下(OK 或 KO),此时只需master再次结帐以重新附加HEAD.


hao*_*lee 12

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

  1. git rebase -i hash-of-preA

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

    pick 8668d21 A
    pick 650f1fc B
    pick 74096b9 C
    
    Run Code Online (Sandbox Code Playgroud)

    将第一个更改pickedit:

    edit 8668d21 A
    pick 650f1fc B
    pick 74096b9 C
    
    Run Code Online (Sandbox Code Playgroud)

    保存并退出.

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

  4. git rebase --continue

现在你的Git提交历史是 preA -- A -- I -- B -- C


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

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


axe*_*nty 9

这是一种避免在我阅读的其他答案中看到的变基期间进行“编辑hack”的策略。

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

break
pick <B's hash> <B's commit message>
pick <C's hash> <C's commit message>
Run Code Online (Sandbox Code Playgroud)

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

可以普遍采用这种策略,以在任何位置插入提交,只需将“ break”放在要插入提交的位置即可。

重写历史记录后,请不要忘记git push -f。有关其他人提取您的分支的常规警告也适用。

  • 这是迄今为止最好的解决方案! (7认同)