Git rebase 而不是合并,正确的做法是什么?
Git rebase instead of merge, the correct way to do it?
我想通过使用 rebase
而不是 merge
来避免在我的远程存储库上重复出现分支交叉点。
为了让您更好地理解我想要实现的目标,请考虑以下情况:
$ git lg
* 2345678 hotfix (HEAD -> master)
* 1234567 foo (origin/master, origin/HEAD)
$ git push
! [rejected] master -> master (fetch first)
$ git fetch
$ git lg
* 2345678 hotfix (HEAD -> master)
| * 3456789 other change (origin/master, origin/HEAD)
|/
* 1234567 foo
通常,解决此问题的标准方法是 merge
后跟 push
。
$ git merge origin/master
$ git lg
* 4567890 Merge remote-tracking branch 'origin/master'
|\
* | 2345678 hotfix (HEAD -> master)
| * 3456789 other change (origin/master, origin/HEAD)
|/
* 1234567 foo
$ git push
我不喜欢这个解决方案,因为在这种特殊情况下我可以很容易地避免分支。因此,让我们使用 git reset --hard head~1
恢复更改并尝试另一种解决方案:
$ git rebase origin/master
First, rewinding head to replay your work on top of it...
Applying: hotfix
$ git lg
* 2345678 hotfix (master)
| * 5678901 hotfix (HEAD)
| * 3456789 other change (origin/master, origin/HEAD)
|/
* 1234567 foo
现在是令人不快的部分,我必须将 master
移回 HEAD
:
$ git branch -D master
$ git checkout -b master
$ git push
$ git branch --set-upstram-to=origin/master master
Branch master set up to track remote branch master from origin.
$ git lg
* 5678901 hotfix (HEAD -> master, origin/master, origin/HEAD)
* 3456789 other change
* 1234567 foo
我的问题是如何简化我的 rebase
并避免不愉快的部分?
我认为最简单的方法是更改您的拉取工作流程。这里有几个选项。
首先可以使用--rebase
标志拉取
git pull --rebase
根据文档,git pull
在其默认配置中执行 fetch
后跟 merge
。使用 --rebase
标志会将 merge
替换为 rebase
:)
其次,您可以设置默认值以始终使用 git pull
执行此操作
git config --global pull.rebase true
我会推荐第一种方法,因为设置默认的 rebase 让我很紧张。我为 git pull --rebase
创建了一个别名 git pr
以使其更容易。这样我就可以在每次拉动时做出决定。
问题是你在本地直接在 master 分支上工作。当您对 master 分支进行一些本地更改并且在您开始后也有上游更改时,您会遇到问题中描述的冲突。因此,避免这种情况的解决方案就是不直接在 master 分支上工作,而是在一个或多个其他本地分支上工作。
所以你把你的修补程序更改放在一个单独的分支上,比如 hotfix_branch
然后 fetch/pull 通常是 master 分支(没有任何冲突!)。当你想交付你的修补程序更改时,你可以重新设置 botfix 分支以保留在新拉出的 master 分支之上,将 hotfix 分支合并到 master 并推送。
示例命令:
$ git pull master
$ git checkout -b hotfix_branch master
$ $EDITOR some.file
# Time passes and changes are made on origin/master
$ git add some.file
$ git commit -m "hotfix"
$ git pull master # No conflicts sine master is "clean"
$ git rebase master hotfix_branch # This step might have merge conflicts but
# if so those will come no matter what you
# do with regards to branching
$ git checkout master
$ git merge hotfix_branch
$ git push
有一个微小的 window 可能会在您拉动和尝试推送 master 之间 origin/master 上发生新的变化,但如果是这样,您只需要做
$ git checkout master # if not already on the master branch
$ git reset origin/master
然后从上面列表中的第二个 pull master
命令重新开始。
我想对已接受的答案提出一种稍微不同的方法。我很少使用 pull
命令,但当我这样做时,我的偏好是在没有指定我希望变基的情况下不自动变基。此外,也许它更罕见,但如果我真的希望进行合并提交怎么办?相反,我的偏好是设置我的配置,如果 fast-forward 不可能,则拉取将失败,使用此配置设置:
[pull]
ff = only
这样我知道我总是可以安全地 pull
并且它会 fast-forward,或者我会得到一个错误,因为我的分支已经分叉。如果出现错误,我可以决定是否要变基或合并(甚至重置到远程!),并相应地进行操作。
我想通过使用 rebase
而不是 merge
来避免在我的远程存储库上重复出现分支交叉点。
为了让您更好地理解我想要实现的目标,请考虑以下情况:
$ git lg
* 2345678 hotfix (HEAD -> master)
* 1234567 foo (origin/master, origin/HEAD)
$ git push
! [rejected] master -> master (fetch first)
$ git fetch
$ git lg
* 2345678 hotfix (HEAD -> master)
| * 3456789 other change (origin/master, origin/HEAD)
|/
* 1234567 foo
通常,解决此问题的标准方法是 merge
后跟 push
。
$ git merge origin/master
$ git lg
* 4567890 Merge remote-tracking branch 'origin/master'
|\
* | 2345678 hotfix (HEAD -> master)
| * 3456789 other change (origin/master, origin/HEAD)
|/
* 1234567 foo
$ git push
我不喜欢这个解决方案,因为在这种特殊情况下我可以很容易地避免分支。因此,让我们使用 git reset --hard head~1
恢复更改并尝试另一种解决方案:
$ git rebase origin/master
First, rewinding head to replay your work on top of it...
Applying: hotfix
$ git lg
* 2345678 hotfix (master)
| * 5678901 hotfix (HEAD)
| * 3456789 other change (origin/master, origin/HEAD)
|/
* 1234567 foo
现在是令人不快的部分,我必须将 master
移回 HEAD
:
$ git branch -D master
$ git checkout -b master
$ git push
$ git branch --set-upstram-to=origin/master master
Branch master set up to track remote branch master from origin.
$ git lg
* 5678901 hotfix (HEAD -> master, origin/master, origin/HEAD)
* 3456789 other change
* 1234567 foo
我的问题是如何简化我的 rebase
并避免不愉快的部分?
我认为最简单的方法是更改您的拉取工作流程。这里有几个选项。
首先可以使用--rebase
标志拉取
git pull --rebase
根据文档,git pull
在其默认配置中执行 fetch
后跟 merge
。使用 --rebase
标志会将 merge
替换为 rebase
:)
其次,您可以设置默认值以始终使用 git pull
git config --global pull.rebase true
我会推荐第一种方法,因为设置默认的 rebase 让我很紧张。我为 git pull --rebase
创建了一个别名 git pr
以使其更容易。这样我就可以在每次拉动时做出决定。
问题是你在本地直接在 master 分支上工作。当您对 master 分支进行一些本地更改并且在您开始后也有上游更改时,您会遇到问题中描述的冲突。因此,避免这种情况的解决方案就是不直接在 master 分支上工作,而是在一个或多个其他本地分支上工作。
所以你把你的修补程序更改放在一个单独的分支上,比如 hotfix_branch
然后 fetch/pull 通常是 master 分支(没有任何冲突!)。当你想交付你的修补程序更改时,你可以重新设置 botfix 分支以保留在新拉出的 master 分支之上,将 hotfix 分支合并到 master 并推送。
示例命令:
$ git pull master
$ git checkout -b hotfix_branch master
$ $EDITOR some.file
# Time passes and changes are made on origin/master
$ git add some.file
$ git commit -m "hotfix"
$ git pull master # No conflicts sine master is "clean"
$ git rebase master hotfix_branch # This step might have merge conflicts but
# if so those will come no matter what you
# do with regards to branching
$ git checkout master
$ git merge hotfix_branch
$ git push
有一个微小的 window 可能会在您拉动和尝试推送 master 之间 origin/master 上发生新的变化,但如果是这样,您只需要做
$ git checkout master # if not already on the master branch
$ git reset origin/master
然后从上面列表中的第二个 pull master
命令重新开始。
我想对已接受的答案提出一种稍微不同的方法。我很少使用 pull
命令,但当我这样做时,我的偏好是在没有指定我希望变基的情况下不自动变基。此外,也许它更罕见,但如果我真的希望进行合并提交怎么办?相反,我的偏好是设置我的配置,如果 fast-forward 不可能,则拉取将失败,使用此配置设置:
[pull]
ff = only
这样我知道我总是可以安全地 pull
并且它会 fast-forward,或者我会得到一个错误,因为我的分支已经分叉。如果出现错误,我可以决定是否要变基或合并(甚至重置到远程!),并相应地进行操作。