如何使用 git rebase 而不需要强制推送?

为了实现 git 的极乐世界,我花了一整天的时间学习如何在当前合并的情况下利用 rebase。

当运行我认为是 git 101流程的内容时(我将在下面详细说明) ,当将更改推回原始内容时,我必须使用 push --force

I'm not the only one - I know that this is covered ground (see 1,2,3,4,5), and I understand the technical reasons 为什么 a force is necessary. My issue is this --- there are many (many) blog entries singing the praises of rebase and how it's changed their lives (see 1,2,push --force0,push --force1 to list a few), but none of them mentions that push --force is part of their flow. However, nearly every answer to the existing stackoverflow questions say things like "yeah, if you're gonna rebase, ya gotta use push --force".

考虑到重新定基拥护者的数量和宗教信仰,我必须相信,使用“推力”并不是再基础流程固有的一部分,如果一个人经常不得不强迫他们的推力,那么他们就做错了

push --force坏事

这就是我的流程,我怎样才能在没有力的情况下达到同样的结果呢?

举个简单的例子

两个分支:

  • V1.0 -一个发布分支,只包含补丁
  • Master -下一个主要版本的所有内容。

我已经为下一个版本提交了一些补丁和一些提交。

premerge

我想把这些补丁合并到我的主程序中,这样它们就不会在下一个版本中丢失。启蒙之前,我只想说:

git checkout master
git merge v1.0

但现在我在努力

git checkout master
git rebase v1.0

所以我来了:

enter image description here

Time for:

git push

No dice.

47803 次浏览

你必须强制推,如果你基地,还有你已经发布了你的变化,对不对?

我使用了大量的 rebase,但是我要么将其发布到强制推送无关紧要的私有版本(例如: 我自己在 GitHub 上的克隆,作为一个 pull 请求的一部分) ,要么在第一次推送之前进行 rebase。

这是您使用 rebase 的工作流的核心,但是不要强制太多地推: 在事情准备好之前不要发布它们,在您推后不要重新基础。

Rebase 是一个很好的工具,但是当您使用它为主题分支创建快进合并到 master 时,它的工作效果最好。例如,您可以根据 master 重新设置 add-new-widget 分支的基础:

git checkout add-new-widget
git rebase -i master

在执行分支到 master 的快进合并之前。例如:

git checkout master
git merge --ff-only add-new-widget

这样做的好处是,您的历史不会有很多复杂的合并提交或合并冲突,因为所有的更改都将在合并之前重新基于 master 的提示。第二个好处是您已经重新定位了基础,但是您不必使用 git push --force,因为您不需要在主分支上修改历史记录。

这当然不是 rebase 的唯一用例,也不是唯一的工作流,但它是我见过的最合理的用法之一。YMMV.

@ CodeGnome 是对的。您不应该将 master 重新建立在 v1.0分支上,而应该将 v1.0分支重新建立在 master 上,这将会产生很大的不同。

git checkout -b integrate_patches v1.0
git rebase master
git checkout master
git merge integrate_patches

创建一个指向 V1.0的新分支,将该新分支移到 master 上,然后将 V1.0补丁的新版本集成到 master 分支。 你最终会得到这样的结果:

o [master] [integrate_patches] Another patch on v1.0
o A patch on v1.0
o Another change for the next major release
o Working on the next major release
|  o [v1.0] Another path on v1.0
|  o A patch on v1.0
| /
o Time for the release

官方的 Git 文件推荐这种使用 rebase 的方法。

我认为你是对的关于 git push --force: 你应该只使用它,如果你犯了一个错误,推一些你不想要的东西。

我认为这种先基础后强制推送的模式有一个很好的用例,它不是错误推送的结果: 自己在多个位置(计算机)处理一个功能分支。我经常这样做,因为我有时在办公室的桌面上工作,有时在家里或客户网站上的笔记本电脑上工作。为了跟上主分支和/或使合并更加干净,我需要偶尔重新设置基础,但是当我离开一台机器去另一台机器上工作时(在那里我只需要拉动) ,我也需要强制推动。只要我是唯一一个在树枝上工作的人就行。

下面是我使用的方法(假设您的分支名称是 Foobar) :

git checkout master              # switch to master
git rebase   foobar              # rebase with branch
git merge -s ours origin/master  # do a basic merge -- but this should be empty
git push origin master           # aaand this should work

tl;dr merge with shared branches, rebase with individual branches. --force-with-lease is a safer alternative to force and should help you achieve said git nirvana without the destructive nature of force.

A general rule of thumb that I've seen work for various teams' workflows is to use merge for shared branches (I.e., master or develop) and use rebase when working on your own feature branch. Here is a typical life cycle of a feature branch

git checkout master
git checkout -b new-feature
git commit -am "commit new work"
git push -u origin new-feature
# have code reviewed, run CI, etc.,
# meanwhile master has new commits
git checkout master
git pull origin
git checkout new-feature
git rebase -i master # -i for interactive rebase allows you to squash intermediate commits
git push --force-with-lease
git merge master

一个简单的英文版本:

  1. 从主人那里创造了一个新的分支
  2. 完成分支上的工作,并推到远程
  3. 以主人为基础
  4. force-with-lease将工作推到远程
  5. 使用一个非常干净的 git 日志合并到 master 中,从而减少来自我们的共享分支的多次合并的混乱,使我们的分支“赶上”最新的 master (共享分支)

第四步非常重要,也是我开始提倡使用 rebase 的主要原因之一。force-with-lease检查远程以查看是否添加了任何新的提交。如果你的 git push被证明是破坏性的,它不会推!

我希望这能让人们对使用 rebase 更有信心。