让我们假设两种情况:
直接在共享开发人员分支上工作:rebase 之后的推送是否也会传输在此 rebase 之前所做的所有提交?
在单独的测试分支中工作并合并到开发者分支中:在 rebase 之后推送开发者分支是否也会传输在 rebase 和后续合并(test->developer)之前所做的所有提交,即使是快进模式?
Schleis 的回答是正确的,但要深入一点,a 的“正常”(但优化)过程是这样的。我们将拟人化您的计算机1 /git-push-process 并将其命名为“Bob”,以及有问题的遥控器“Rem”。交换是这样的:git push [remote [refspecs ...]]
BOB:“嗨,我有一些分支 refspecs 给你,你有什么?”
REM:“我有master
, deploy
, develop
, 和test
。”
BOB:“好的,所以我已经承诺cabfa4e
作为负责develop
人和fedcafe
负责人test
,我想向你发送你需要的东西。”
REM:“好吧,我已经开始了fedcafe
,test
但我已经badf00d
开始了develop
……”
BOB:“啊,好吧,我明白badf00d
了,我会给你这些新的提交和树/blob/标签对象[交出一长串对象数据,打包成一个“瘦”包]。”
REM:[停下来消化包,运行各种钩子,验证 Bob 给他的东西是好的,更新是好的develop
;如果一切顺利] “谢谢鲍勃!”
鲍勃:“好的,再见,再见!”
(当这个对话结束时,Bob 知道 Rem-the-remote 现在cabfa4e
在 branch 上develop
,所以 Bob 也更新remotes/rem/develop
了。)
这一切的关键在于,Bob 和 Rem 不知道,甚至不关心,当他们交换数据并且 Bob 通过新的 git 对象(提交、树、blob 和/或带注释的标签)。完成后,Rem 拥有 Bob 发送的任何内容,如果他“接受”了它(没有“拒绝”参考更新),Bob 将更新他对 Rem 拥有的内容的记录。
同样重要的是,Bob 只是将 refspecs 交给了 Rem。
假设您决定“回退”(“删除”)一个或多个提交,从cabfa4e
back 到badf00d
,并执行强制推送。对话有点短——Rem 已经拥有了所有的对象——而且 Rem 更有可能说“不,不可以,因为我不回滚提交”。Bob 会告诉 Rem 您要求“强制”推送(Rem 仍然可以说“不”,但“内置默认”是“除非强制”,而您要求“强制”)。
或者,假设您没有决定回退任何内容,但 Rem 早前从 Jan 那里获得了新的提交,而您的计算机 Bob 上没有它们。Rem 现在有develop
at commit c0ffeee
,而 Bob 根本没有。他们最早的同步点是(仍然)在badf00d
。鲍勃可以向雷姆提议:“不管怎样,让我们开始吧develop
,cabfa4e
我会给你从上到下的一切badf00d
。cabfa4e
” 雷姆会说“不,你错过了一些东西(即,这不是快进)。除非你说强制,否则我不会那样做。” 获取和(合并/变基)、更新 Bob 以拥有c0ffeee
(可能还有其他提交)取决于您。
这都是关于提交图的。您(通过 Bob)建议远程(Rem)通过更改refs/heads/
标签以指向不同的提交来更改 Rem 提交图的某些部分;并且您(Bob)提供图表的新部分,以及所需的任何其他对象;然后遥控器(Rem)根据 Rem 的规则(钩子)说“OK”或“not OK”。默认的内置规则是:“如果refs/heads/
标签以快进方式移动,则为是。否则,如果强制则为是,如果不强制则为否。”
1 “不要将计算机拟人化;他们讨厌那样。”
git push
尝试将远程存储库更新到与您正在推送的本地分支相同的状态。因此,只要历史记录兼容,该分支中的任何提交都将添加到远程。您不是在推送单个提交,而是推送整个分支的状态。