简体   繁体   English

重新设置从主分支分支出来的分支的分支时要采取的步骤

[英]steps to take when rebasing a branch thats branched off a branch which is branched off a main branch

I keep getting nightmare rebases and I think its because Im taking the wrong steps.我一直在做噩梦,我认为这是因为我采取了错误的步骤。

I've got 3 branches... mainbranch, branch1, branch2... branch1 is a branch off mainbranch... branch2 is a branch off branch1我有 3 个分支... mainbranch、branch1、branch2... branch1 是 mainbranch 的一个分支... branch2 是 branch1 的一个分支

branch1 is 1 commit ahead of mainbranch branch2 is 1 commit ahead of branch1 branch1 比 mainbranch 提前 1 次提交 branch2 比 branch1 提前 1 次提交

So its in this state that I have problems when I... git fetch -p;所以它在这个 state 中我遇到问题... git fetch -p; git pull -r... on mainbranch I now want to bring the new changes on mainbranch into branch1 and branch2. git pull -r... on mainbranch 我现在想将 mainbranch 上的新更改带入 branch1 和 branch2。 This is what I am currently doing:这就是我目前正在做的事情:

git checkout mainbranch
git fetch -p
git pull -r
git checkout branch1
git rebase -i mainbranch (i dont squash commits or anything like that)
git checkout branch2
git rebase -i branch1 <<< this causes the problem

When I run that last command I have a nightmare with conflicts.当我运行最后一个命令时,我做了一场冲突的噩梦。 I am assuming because somehow when i did the first rebase in the steps above that it messed with the commit hashes and has confused git.我假设因为不知何故,当我在上述步骤中进行第一次变基时,它弄乱了提交哈希并混淆了 git。 What steps should I take to do this correctly?我应该采取哪些步骤来正确执行此操作? thanks谢谢

The goal here is to end up in the initial state (branches 1 commit ahead of each other) but with all the changes from mainbranch in all the branches这里的目标是在最初的 state 中结束(分支 1 彼此提前提交),但所有分支中的所有更改都来自 mainbranch

pull -r rebases the new commits from your mainbranch , so they really get new hashes, and this makes git recognize them differently. pull -r从你的mainbranch重新提交新的提交,所以他们真的得到了新的哈希,这使得 git 以不同的方式识别它们。 I'm not sure how much text changes affect this behavior (I guess they do the most), but this (only?) can happen when rebasing commits that modify the same files.我不确定有多少文本更改会影响此行为(我猜他们做的最多),但这(仅?)可能会在修改相同文件的重新提交时发生。 What you need is only to tell git to rebase the branch1 and branch2 branches with their single commits (I'm assuming this is clear from your question) because git does not track them itself.您只需要告诉branch1使用它们的单个提交来重新设置 branch1 和branch2分支(我假设这从您的问题中很清楚),因为 git 本身不会跟踪它们。

git checkout mainbranch
git fetch -p
git pull --rebase

# rebase branch 1
git rebase --onto mainbranch branch1~1 branch1

# rebase branch 2
git rebase --onto branch1 branch2~1 branch2

Note that the rebase commands tell git to start rebasing according to these rules:请注意,变基命令告诉 git 根据以下规则开始变基:

  • --onto <base> tells git where to start building new commits onto ( --onto mainbranch and then --onto branch1 ) --onto <base>告诉 git 从哪里开始构建新的提交( --onto mainbranch然后--onto branch1
  • <upstream>~1 tells git the range/number of patches to be applied from (literally one only) <upstream>~1告诉 git 要应用的补丁的范围/数量(实际上只有一个
  • <downstream> tells git the branch name to rebase <downstream>告诉 git 要变基的分支名称

So, it's something like "git please rebase the branch branch1 onto the current mainbranch , only one ( ~1 ) patch please", and then the same for the branch1-branch2 rebasing.因此,它类似于“git 请将分支 branch1 mainbranch branch1 ,请只使用一个 ( ~1 ) 补丁”,然后对于 branch1-branch2 重新定位也是如此。

It might be easier to track down why it gets happening when using interactive rebase (at least you can see what causes that):使用交互式 rebase 时可能更容易找出它发生的原因(至少你可以看到是什么原因造成的):

git checkout mainbranch
git fetch -p
git pull --rebase

# rebase branch 1
git checkout branch1
git rebase -i mainbranch
# note that the editor opens with more than one command: two or more picks (depends on the number of commits on main branch)
# simply remove all commands except the last `pick` command that picks the only commit from the branch1 branch

# rebase branch 2
git checkout branch2
git rebase -i branch1
# the same here: note that this will also include the original commit from branch1 that should be dropped too
# keep the last `pick` command only

Once it's done, in both scenarios (you decide which you prefer to follow), git log --oneline would produce something like:完成后,在这两种情况下(您决定要遵循哪种情况), git log --oneline将产生如下内容:

CCCCCC (branch2) the only commit from branch2
BBBBBB (branch1) the only commit from branch1
AAAAAA (mainbranch) the tip commit at mainbranch
...

If you're familiar with what happens there and you feel safe with doing rebases and understand that something may go wrong, you can then even do something like:如果您熟悉那里发生的事情,并且您对执行 rebase 感到安全,并且了解可能出现 go 错误,那么您甚至可以执行以下操作:

git checkout mainbranch
git fetch -p
git pull --rebase

# rebase branch 1
git rebase master
git rebase --skip # assuming conflicts will occur here
                  # and this is equivalent to dropping the current patch from the interactive rebase (scenario 2 above)
                  # or excluding the commit from the commit range (scenario 1 above)
# possibly more `git rebase --skip` (unless the only patch is applied)

# rebase branch 2
git rebase branch1
git rebase --skip # one time than the previous rebase because of the old "branch1 commit on branch2" commit

I prefer the last one because I can see it right in my bash prompt (number of patches to apply, aheads/behinds after the rebase is completed, etc), but I always double check the result using git log before force-pushing.我更喜欢最后一个,因为我可以在我的 bash 提示符中看到它(要应用的补丁数量、rebase 完成后的前后变化等),但我总是在强制推送之前使用git log仔细检查结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM