这个问题的答案显示了如何选择性地推送本地提交,但似乎这些是提示的本地提交。
如果我已经合并了来自源的新更改,以便它们与我的提交穿插在一起(并且最后一次提交是“合并”消息),我能做些什么来只推送其中一些提交吗?或者我是否需要在合并和重置/存储我想遗漏的提交之前进行分支?
您需要创建一个引用相关提交的 refspec,并推送该 refspec。
这背后的原因有点混乱。在一个push
(或任何其他对象传输序列)中传输的实际对象集不一定限于您的想法。有时推送会推送“未使用”的 repo 对象,因为客户端(进行推送)和服务器(接收对象包)之间的同步是松散指定的。它保证所有需要的对象都会到达那里,但可能会推送一些不必要的对象。实际上,要弄清楚“什么是必要的”可能需要更多的沟通,而不仅仅是推送所有内容,尤其是在发送/接收序列中进行所有压缩的情况下。
因此,“推送”内部发生的事情是客户端发送一个装满对象的大球(特别是“瘦包”),然后——在这些对象被安全地安置在服务器的存储库中之后——发送一个集合“参考标签”:
refs/heads/zorg = object 00ac1d1f1ab1ec0ffee5c01ec0idf1dd1edeedee
refs/tags/skin = object 5011d1f1ab1ebac1110515be11e5be111c05ed0e
等等。服务器通过 git pre-receive 和 update 挂钩运行这些 ref-updates 以验证它们是否正常,如果是,则将它们存储在服务器的 refs 中。(如果需要,钩子可以检查这些对象。这让钩子可以检查标签是否“轻量级”,直接引用提交,或“注释”,引用 repo 中的标签对象,例如。)
我将在这里补充一点,我认为您的问题暗示了对分支实际工作方式的误解。分支是一种“隐含的”数据结构。Git 有两个基本概念协调创建一个“分支”:它有分支提示标签,它命名一个单一的提交;它有提交,每个提交都带有零个或多个“父提交”ID。例如,master
分支是分支提示名称 ( refs/heads/master
)。但这只会让你获得一次提交,即分支的尖端。要查找分支“上”的内容,您可以从那里开始查看该提交的父级或父级。在那一刻,每个父提交也“在”master
分支上,并且每个父母的父母都在它上面,依此类推。如果你有:
M1 -- M2 -- M3 -- M4 <-- master
\
B1 -- B2 -- B3 <-- branchB
\ /
D1 -- D2 <-- develB
然后 commitB3
是“on” branchB
,因为它是 , and 的尖端branchB
,并且D2
和B2
也是“on”分支,因为B3
这两个 commit 都作为其父项。
如果你根本不想要D2
,branchB
但你确实想要D1
它,你必须做出一个新的(而且完全不同的)提交——让我们称之为——它B4
有它B2
的D1
父母:
M1 -- M2 -- M3 -- M4 <-- master
\
| ------B4 <-- branchB
| / |
B1 -- B2 -- B3 | <-- branchB-old [or abandoned entirely]
\ / |
D1 -- D2 | <-- develB
\ /
----------
再次branchB
简单地命名一个分支提交,但这个不同于B3
.
推送上述内容(带有 的混乱B4
)实际上可能会将提交推B3
送到服务器,但只要没有标签,就不会有人看到它,并且最终会被服务器垃圾收集。