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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32315156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 03:32:53  来源:igfitidea点击:

How to inject a commit between some two arbitrary commits in the past?

git

提问by BartoszKP

Suppose I have the following commit history on my local-only branch:

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

A -- B -- C

How do I insert a new commit between Aand B?

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

回答by SLaks

It's even easier than in OP's answer.

它比OP的答案更容易。

  1. git rebase -i <any earlier commit>. This displays a list of commits in your configured text editor.
  2. Find the commit you want to insert after (let's assume it's a1b2c3d). In your editor, for that line, change pickto edit.
  3. Begin the rebase by closing your text editor (save your changes). This leaves you at a command prompt with the commit you chose earlier (a1b2c3d) as if it has just been committed.
  4. Make your changes and git commit(NOTamending, unlike most edits). This creates new a commit afterthe one you chose.
  5. git rebase --continue. This replays the successive commits, leaving your new commit inserted in the correct place.
  1. git rebase -i <any earlier commit>. 这会在您配置的文本编辑器中显示提交列表。
  2. 找到您想在之后插入的提交(假设它是a1b2c3d)。在您的编辑器中,对于该行,更改pickedit.
  3. 通过关闭文本编辑器(保存更改)开始变基。这会让您在命令提示符处看到您之前选择的提交 ( a1b2c3d) ,就好像它刚刚被提交一样
  4. 进行更改和git commit(与大多数s不同,不是修改edit)。这会您选择的提交之后创建新的提交。
  5. git rebase --continue. 这将重播连续的提交,将您的新提交插入正确的位置。

Beware that this will rewrite history, and break anyone else who tries to pull.

请注意,这将改写历史,并破坏任何试图拉动的人。

回答by BartoszKP

Turns out to be quite simple, the answer found here. Suppose you're on a branch branch. Perform these steps:

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

  • create a temporary branch from the commit after you want to insert the new commit (in this case commit A):

    git checkout -b temp A
    
  • perform the changes and commit them, creating a the commit, let's call it N:

    git commit -a -m "Message"
    

    (or git addfollowed by git commit)

  • rebase the commits you want to have after the new commit (in this case commits Band C) onto the new commit:

    git rebase temp branch
    
  • 在要插入新提交(在本例中为 commit A)后,从提交创建一个临时分支:

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

    git commit -a -m "Message"
    

    (或git add紧随其后git commit

  • 在新提交(在本例中为 commitsBC)之后将您想要的提交变基到新提交上:

    git rebase temp branch
    

(possibly you need to use -pto preserve merges, if there were any - thanks to a no longer existing commentby ciekawy)

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

  • delete the temporary branch:

    git branch -d temp
    
  • 删除临时分支:

    git branch -d temp
    

After this, the history looks as follows:

在此之后,历史记录如下:

A -- N -- B -- C

It is of course possible that some conflicts will appear while rebasing.

当然,rebase 时可能会出现一些冲突。

In case your branch is not local-only this will introduce rewriting history, so might cause serious problems.

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

回答by Matthew

Even easier solution:

更简单的解决方案:

  1. Create your new commit at the end, D. Now you have:

    A -- B -- C -- D
    
  2. Then run:

    $ git rebase -i hash-of-A
    
  3. Git will open your editor and it will look like this:

    pick 8668d21 B
    pick 650f1fc C
    pick 74096b9 D
    
  4. Just move D to the top like this, then save and quit

    pick 74096b9 D
    pick 8668d21 B
    pick 650f1fc C
    
  5. Now you will have:

    A -- D -- B -- C
    
  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
    

回答by haolee

Assuming that the commit history is preA -- A -- B -- C, if you want to insert a commit between Aand B, the steps are as follows:

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

  1. git rebase -i hash-of-preA

  2. Git will open your editor. The content may like this:

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

    Change the first pickto edit:

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

    Save and Exit.

  3. Modify your code and then git add . && git commit -m "I"

  4. git rebase --continue

  1. git rebase -i hash-of-preA

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

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

    将第一个更改pickedit

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

    保存并退出。

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

  4. git rebase --continue

Now your Git commit history is preA -- A -- I -- B -- C

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



If you encounter a conflict, Git will stop at this commit. You can use git diffto locate conflict markers and resolve them. After resolving all conflicts, you need to use git add <filename>to tell Git that the conflict has been resolved and then rerun git rebase --continue.

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

If you want to undo the rebase, use git rebase --abort.

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

回答by axerologementy

Here's a strategy that avoids doing an "edit hack" during the rebase seen in the other answers I've read.

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

By using git rebase -iyou obtain a list of commits since that commit. Just add a "break" at the top of the file, this will cause the rebase to break at that point.

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

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

Once launched, git rebasewill now stop at the point of the "break". You can now edit your files and create your commit normally. You can then continue the rebase with git rebase --continue. This may cause conflicts you'll have to fix. If you get lost, don't forget you can always abort using git rebase --abort.

一旦启动,git rebase现在将在“中断”点停止。您现在可以编辑您的文件并正常创建您的提交。然后,您可以继续使用git rebase --continue. 这可能会导致您必须修复的冲突。如果您迷路了,请不要忘记您始终可以使用git rebase --abort.

This strategy can be generalised to insert a commit anywhere, just put the "break" at the spot where you want to insert a commit.

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

After rewriting history, don't forget to git push -f. The usual warnings about other people fetching your branch apply.

改写历史后,别忘了git push -f。有关其他人获取您的分支的常见警告适用。

回答by RomainValeri

Many good answers here already. I just wanted to add a "no rebase" solution, in 4 steps.

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

One advantage of this solution isthat you don't touch your branch until the final step, when you're 100% sure you're OK with the end result, so you have a very handy "pre-confirmation" step allowing for AB testing.

此解决方案的一个优点是,在最后一步之前您不会接触分支,当您 100% 确定您对最终结果没问题时,因此您有一个非常方便的“预确认”步骤,允许 AB测试



Initial state(I've assumed masterfor your branch name)

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

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


1) Start by pointing HEAD at the right place

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

git checkout A

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

(Optionnally here, rather than detaching HEAD, we could have created a temporary branch with git checkout -b temp A, which we would need to delete at the end of the process. Both variants work, do as you prefer since everything else remains the same)

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



2) Create the new commit D to be inserted

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)


3) Then bring copies of the last missing commits B and C(would be same line if there were more commits)

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)

( comfortable AB Testing here if needed )

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

Now is the moment to inspect your code, test anything that needs to be tested, and you can also diff / compare / inspect what you hadand what you would getafter the operations.

现在是检查您的代码、测试任何需要测试的内容的时候了,您还可以比较/比较/检查您拥有的内容以及操作后您将获得的内容。



4)Depending on your tests between Cand C', either it is OK or it is KO.

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

(EITHER) 4-OK) Finally, move the ref of master

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

git branch -f master HEAD

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

(OR) 4-KO) Just leave masterunchanged

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

If you created a temporary branch, just delete it with git branch -d <name>, but if you went for the detached HEAD route, no action needed at all at this point, the new commits will be eligible for garbage collection just after you reattach HEADwith a git checkout master

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

In both those cases (OK or KO), at this point just checkout masteragain to reattach HEAD.

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