TL;DR版本:让每个人使用
git pull --rebase
。
如果我理解正确,您的情况是这样的。
A - B - C [m]
\
D - E - F [f]
\
G - H - I [d]
m表示主分支,f表示特性分支,d表示���发分支。你想要能够将f分支rebase到m分支上,也希望能够将d分支rebase到新的f分支上。
G1 - H1 - I1 [d]
/
D1 - E1 - F1 [f]
/
A - B - C [m]
\
D - E - F
\
G - H - I
答案是让每个人运行
git pull --rebase
,这相当于运行
git fetch
和
git rebase
。下面是它的工作原理。在主分支(commit C)有新工作推送后,仓库将如下所示。
origin
A - B - C [m]
\
D - E - F [f]
\
G - H - I [d]
feature branch maintainer
A - B [m][o/m]
\
D - E - F [f][o/f]
\
G - H - I [o/d]
dev branch maintainer
A - B [m][o/m]
\
D - E - F [o/f]
\
G - H - I [d][o/d]
特性分支的维护者决定更新,因此他们执行 git pull --rebase origin master
命令。这会执行 git fetch origin
和 git rebase origin/master
命令,结果如下。
feature branch maintainer
D1 - E1 - F1 [f]
/
A - B [m]- C [o/m]
\
D - E - F [o/f]
\
G - H - I [o/d]
然后他们会执行
git push origin
命令(我相信他们需要强制执行),这是结果。
origin
D1 - E1 - F1 [f]
/
A - B - C [m]
\
D - E
\
G - H - I [d]
feature branch maintainer
D1 - E1 - F1 [f][o/f]
/
A - B [m]- C [o/m]
\
D - E
\
G - H - I [o/d]
dev branch maintainer
A - B [m][o/m]
\
D - E - F [o/f]
\
G - H - I [d][o/d]
现在,dev分支的维护者想要更新,却毫不知情feature分支发生了什么。他们使用git pull --rebase
命令,它等同于git fetch origin
和git rebase origin/feature
命令。在执行fetch命令后,结果如下所示。
dev branch maintainer
D1 - E1 - F1 [o/f]
/
A - B [m]- C[o/m]
\
D - E
\
G - H - I [d][o/d]
然后执行
git rebase origin/feature
。
dev branch maintainer
G1 - H1 - I1 [d]
/
D1 - E1 - F1 [o/f]
/
A - B [m]- C[o/m]
\
D - E
\
G - H - I [o/d]
他们可以使用--force
参数来强制推送。
你会注意到dev分支现在是在F1上,而不是原来的E1。如果你想保持原样,你需要特别地将其变基到E1上。
如果Git无法确定D和E实际上不属于dev分支,你可能会遇到这种情况。
dev branch maintainer
D2 - E2 - G1 - H1 - I1 [d]
/
D1 - E1 - F1 [o/f]
/
A - B [m]- C[o/m]
\
D - E
\
G - H - I [o/d]
Git应该能够使用“补丁ID”来解决这个问题,它类似于提交ID,但只检查内容而不涵盖其他信息。如果无法解决,请尝试更新Git并查看是否有所帮助。如果仍然无法解决,则属于git-rebase文档所称的“困难情况”。您需要使用
--onto
明确告诉Git要将哪些提交作为基础进行变基。幸运的是,引用日志包含了功能分支的先前位置f@ {1},可以用作参考。
git rebase --onto f f@{1}
这里说的是将当前分支(d)变基到f,但只从d到f@{1}(也就是f之前的位置)进行变基。
我将git pull --rebase
别名为git repull
。我几乎总是这样做,它相当安全,通常都是正确的做法。您可以使用git config --global pull.rebase true
将其配置为默认值。
更多信息,请参见git-rebase
文档中有关从上游变基的恢复说明。