git - 对从主分支分支的分支进行 rebase 时要采取的步骤

标签 git

我不断收到噩梦般的 rebase ,我认为这是因为我采取了错误的步骤。

我有 3 个分支 ... mainbranch、branch1、branch2 ...branch1 是 mainbranch 的一个分支 ...branch2 是branch1 的一个分支

  • branch1 比 mainbranch 早 1 次提交
  • branch2 比branch1 早 1 次提交

因此,在这种状态下,当我... git fetch -p; 时,我遇到了问题。 git pull -r ... 在主分支上。我现在想将 mainbranch 上的新更改引入到branch1 和branch2 中。这就是我目前正在做的事情:

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

当我运行最后一个命令时,我做了一场冲突的噩梦。我假设是因为不知何故,当我在上述步骤中进行第一次 rebase 时,它弄乱了提交哈希并混淆了 git。我应该采取什么步骤才能正确执行此操作?

这里的目标是最终处于初始状态(分支 1 相互提前提交),但所有分支中都包含主分支的所有更改

最佳答案

pull -r重新设定来自 mainbranch 的新提交,所以它们确实得到了新的哈希值,这使得 git 以不同的方式识别它们。我不确定有多少文本更改会影响此行为(我猜它们影响最大),但这(仅?)在修改相同文件的 rebase 提交时可能会发生。你所需要的只是告诉 git rebase branch1branch2具有单个提交的分支(我假设从你的问题中可以清楚地看出这一点),因为 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

请注意,rebase 命令告诉 git 根据以下规则开始 rebase :

  • --onto <base>告诉 git 从哪里开始构建新的提交( --onto mainbranch 然后 --onto branch1 )
  • <upstream>~1告诉 git 要应用的补丁的范围/数量(仅一个)
  • <downstream>告诉 git 要 rebase 的分支名称

所以,这就像“git 请将分支 branch1 rebase 到当前 mainbranch ,请只打一个( ~1 )补丁”,然后对branch1-branch2 rebase 也是如此。

使用交互式 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

完成后,在这两种情况下(您决定更喜欢遵循哪一种),git log --oneline会产生类似的东西:

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

如果您熟悉那里发生的情况,并且您对进行 rebase 感到安全并且了解可能会出现问题,那么您甚至可以执行以下操作:

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

我更喜欢最后一个,因为我可以在 bash 提示符中看到它(要应用的补丁数量、 rebase 完成后的提前/落后等),但我总是使用 git log 仔细检查结果在强制推送之前。

关于git - 对从主分支分支的分支进行 rebase 时要采取的步骤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65790387/

相关文章:

git - 将旧 git 历史记录添加到新存储库

服务器上的 Git(windows server 2012)

git - 在远程工作树上运行 git 命令 (GIT_WORK_TREE=/path)

git - 如何使用 GitLab 在服务器端触发 git hook

git - 为什么 git stash pop 说它无法从存储条目中恢复未跟踪的文件?

git - 如何在每次推送时在GitHub工作流中运行commitlint

git - 为什么 "git push"使用 MySysGit 1.7.4 会无限期地卡在那里?

php - 我可以在没有 ssh 访问权限的情况下在 PHP 中使用 shell_exec 或反引号吗?

Git:在裸存储库中更改事件分支的正确方法?

c++ - cmake:在主 cmakelists 中使用之前从 git 检索库