我已经在与另一个开发人员的项目中使用Git几个月了。我在SVN方面拥有多年的经验,所以我想我为这段感情带来了很多麻烦。
我听说Git非常适合分支和合并,到目前为止,我只是看不到它。当然,分支是非常简单的,但是当我尝试合并时,一切都会陷入困境。现在,我已经习惯了SVN,但是在我看来,我只是将一个低于标准的版本控制系统换成了另一个。
我的伴侣告诉我,我的问题源于我想要合并Willy-nilly的愿望,在许多情况下,我应该使用rebase而不是合并。例如,这是他制定的工作流程:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature
git checkout master
git merge my_new_feature
本质上,创建一个功能分支,始终将其从master转移到master,然后从分支合并回到master。需要注意的重要一点是,分支始终位于本地。
这是我开始的工作流程
clone remote repository
create my_new_feature branch on remote repository
git checkout -b --track my_new_feature origin/my_new_feature
..work, commit, push to origin/my_new_feature
git merge master (to get some changes that my partner added)
..work, commit, push to origin/my_new_feature
git merge master
..finish my_new_feature, push to origin/my_new_feature
git checkout master
git merge my_new_feature
delete remote branch
delete local branch
(我认为)有两个基本区别:我总是使用merge而不是重新设置基础,并且将功能分支(和功能分支的提交)推送到远程存储库。
我之所以选择远程分支机构,是因为我希望在工作时备份自己的工作。我们的存储库将自动备份,如果出现问题可以将其还原。我的笔记本电脑不是,还是不够彻底。因此,我讨厌笔记本电脑上没有其他地方镜像的代码。
我之所以选择合并而不是重新设置基准,是因为合并似乎是标准的,而重新确定基准似乎是一项高级功能。我的直觉是我要尝试的不是高级设置,因此不需要重新设置基准。我什至仔细阅读过有关Git的新《实用程序设计》一书,它们涵盖了合并的内容,几乎没有提及重新设置基础。
无论如何,我在最近的分支上跟踪我的工作流程,当我尝试将其合并回master时,一切都陷入了困境。与本不应该发生的事情存在大量冲突。冲突对我来说毫无意义。我花了一天的时间来整理所有内容,最终以强迫推送到远程主机的方式达到了顶峰,因为我的本地主机解决了所有冲突,但是远程主机仍然不满意。
这样的“正确”工作流程是什么?Git应该使分支和合并变得非常容易,而我只是没有看到它。
更新2011-04-15
这似乎是一个非常受欢迎的问题,所以我认为自从我第一次提出问题以来,我会根据自己两年的经验进行更新。
事实证明,至少在我们看来,原始工作流程是正确的。换句话说,这就是我们所做的并且有效:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge my_new_feature
实际上,我们的工作流程有些不同,因为我们倾向于壁球合并而不是原始合并。(注:这是有争议的,请参见下文。)这使我们能够将整个功能分支变成对master的单个提交。然后,我们删除功能分支。这使我们可以逻辑地在master上构造我们的提交,即使它们在我们的分支上有些混乱。因此,这就是我们要做的:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge --squash my_new_feature
git commit -m "added my_new_feature"
git branch -D my_new_feature
壁球合并争议 -正如一些评论者所指出的那样,壁球合并将丢弃功能分支上的所有历史记录。顾名思义,它将所有提交压缩为一个。对于小功能,这很有意义,因为它可以将其压缩为单个包装。对于较大的功能,这可能不是一个好主意,特别是如果您的单个提交已经是原子的。这确实取决于个人喜好。
Github和Bitbucket(其他?)拉取请求 -如果您想知道合并/变迁与拉取请求之间的关系,我建议您按照上述所有步骤进行操作,直到准备好合并回主服务器为止。您只需接受PR,而不是与git手动合并。请注意,这不会进行壁球合并(至少默认情况下不是),但是在请求请求社区中,非壁球,非快进是可接受的合并约定(据我所知)。具体来说,它的工作方式如下:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git push # May need to force push
...submit PR, wait for a review, make any changes requested for the PR
git rebase master
git push # Will probably need to force push (-f), due to previous rebases from master
...accept the PR, most likely also deleting the feature branch in the process
git checkout master
git branch -d my_new_feature
git remote prune origin
我已经爱上了Git,再也不想回到SVN了。如果您在挣扎,请坚持下去,最终您会在隧道尽头看到光明。
rebase
理解