今天有一个需求。本地有一个代码库,我希望推送到自己的远程代码库的master(A/proj.git)作为存储;同时还要发布到另一个人的远程代码库,作为一个全新的、不带他的提交历史的分支(B/proj2.git),因为二者文件完全不相关。不过,B/proj2的feat分支现在并不存在。首先想到的方案就是,在B上创建一个孤儿(orphan)分支 feat
,然后本地master直接 git push B feat
不就好了?嘛,被 Git 的各种机制坑了。
PS. 2016年8月到今年1月的文章,以后会放上来……
我进行了这样的操作:
|
好,到这里都没问题。我已经在远程(BitBucket)上创建了 proj
这个项目,推送没问题。然后到了开orphan分支的事情了。然而 BitBucket 不支持创建孤儿分支(GitHub 也不支持),只支持从master创建新分支。那只好手工上了。
|
我觉得,既然在本地创建了远程B,我的master分支应该不用跟踪proj2就能推送(而且我也不希望master跟踪proj2)才对。于是收到了报错:
|
我对 Git 分支的表示有略微了解,大概就是某个 refs/...
下的东西。于是略微谷歌一下,找到了一篇 StackOverflow 上的回答。照葫芦画瓢:
|
然而又收到了一样的错误。哎,先将目标定为创建一个 B/proj2 的孤儿分支吧。遵循指导(1和2),在新的目录下:
|
好了,到这里我觉得可以直接发布分支了,于是尝试:
|
然而无法推送。想了想,是因为没有提交吧!添加了一个空文件后提交,推送成功。此时 B/proj2 上出现了一个孤儿分支feat,带有一个提交。
但真正文件的推送还没解决。考虑到网上许多人都是checkout了本地分支后再操作的,好吧,我放弃直接在master上操作了,于是创建了一个新分支branch2:
|
继续报错:
|
历史冲突,那用本地孤儿分支又如何呢?
|
这次拉取倒是没问题:
|
然而我惊恐地发现,由于是孤儿分支而且进行了 git rm -rf
,目录下空空如也。那赶快合并吧:
|
又是喜闻乐见的报错:
|
究其原因,是因为我之前为了在远程创建这个分支而提交的一个空文件导致了历史冲突。那……直接checkout呢?
|
这一次,出现了不同的东西:
|
好的,希望很大!看到这个提示,就表明推送是因为修改时间冲突(我先在本地提交,再去创建远程孤儿分支下的空文件)。既然如此,强制推送就行了:
|
现在就可以了。BitBucket 上显示,新分支feat有相对于B/proj2的master两个超前提交(我在本地的修改历史)和若干个落后提交(master已有的历史)。这是正确的。
不过好像有一个副作用,在推送之前我有个文件是有改动未提交的,经过这次推送后这个改动消失了,不知是不是某个操作隐含意义的问题。
总结:正确的创建和推送流程——推送到 B/proj2.git 的 feat 分支
在临时目录:
|
在工作目录:
|
话说在各个命令间,“feat”是固定的吗?本地的分支和远程分支要同名吗?不确定,不过根据 PR 的两个相关分支间可以名字不同,猜测这里也可以不同。但为了不造成混乱,最好取一样的名字吧。