如何在不需要强制推送的情况下使用git rebase?


92

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

在运行我认为是git 101的流程(我在下面说明)时,必须push --force将更改推回原点。

我不是唯一的一个-我知道,这是覆盖地面(见12345),我理解的技术原因,为什么力是必要的。我的问题是这样的---有歌声底垫的赞美很多(多)发表的博客以及它如何改变他们的生活(见1234,列出了几个),但他们没有提到push --force是的一部分他们的流量。但是,几乎所有对现有stackoverflow问题的回答都说“是的,如果您要重新设置基础,您必须使用push --force”。

考虑到rebase拥护者的数量和宗教信仰,我必须相信使用'push --force'并不是rebase流程的固有部分,并且如果人们经常不得不强迫自己推送,那么他们在做错事

push --force件坏事

这就是我的流程。 没有力量我能以什么方式获得相同的结果?

简单的例子

两个分支:

  • v1.0-版本分支,仅包含补丁
  • 大师 -下一个主要版本的所有内容。

我有一些补丁提交,还有一些针对下一个发行版的提交。

预合并

我想将这些修补程序合并到我的母版中,以使它们不会在下一发行版中丢失。启蒙前我会简单地:

git checkout master
git merge v1.0

但是现在我正在尝试

git checkout master
git rebase v1.0

所以现在我在这里:

在此处输入图片说明

的时间:

git push

没有骰子。

Answers:


43

变基是一个很棒的工具,但是当您使用它为主题分支创建快速转发合并到母版时,它最有效。例如,您可以将master的add-new-widget分支作为基础:

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

在将分支快速合并到master之前。例如:

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

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

当然,这不是变基的唯一用例,也不是唯一的工作流,但这是我所见过的最明智的用法之一。YMMV。


4
感谢CG,我认为“使用它来创建快速合并”是关键。它不适用于我上面有两个活动分支(开发分支和发布分支)的情况,但是它似乎非常适合临时主题分支,这些临时主题仅在有限的时间范围内是必需的,然后可以合并后将其删除。再次感谢。
罗伊·特鲁伊洛夫

1
我确实理解这一点,但最初的问题仍然存在。我认为实际答案是@Fabien Quatravaux
IsmailS 2014年

4
好吧,您仍然必须强制按下1.0分支,不是吗?至少,这就是我时常发生的事情。Fabiens方法可以防止这种情况的发生。
joerx 2014年

23

@CodeGnome是正确的。您不应该在master的v1.0分支上重新建立master的基础,而在master的v1.0分支上重新建立基础,这将会有所作为。

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:只有在犯了错误并推送了您不想要的内容时,才应使用它。


我认为这是针对OP中特定问题的最佳答案。您创建一个临时合并分支并以此为基础,然后合并到master并推送到原点。不必将临时分支推到原始位置。我唯一要提供的其他建议是建立一个develop或qa分支,在该分支中可以对合并/基于基础的代码进行限定。合格后,此代码将仅被ff合并到master中。如果您的资格鉴定过程花费太长时间,则可以轻松进行热修复。这基本上是“ git flow”过程。
贾维德·贾梅

感谢Fabien,好的答案。对于那些只想将更改集成到其中master并且不介意合并功能分支本身的人,可以使用以下方法完成:git checkout my-branch; git rebase master; git checkout master; git merge my-branch
Siavas,

17

如果要重新设置基准,则必须强制执行,并且已经发布了更改,对吗?

我使用了整个库,但我要么发布到某个强制推送无关紧要的私有内容(例如:作为拉取请求的一部分,在GitHub上我自己的克隆),要么在第一次推送之前重新部署。

这是工作流的核心,在其中使用了重新设置基准,但是不要强行推送:不要在事情准备好之前就发布它们,在按下之后不要重新编制基准。


谢谢丹。您能告诉我如何实现上述目标吗?这是否不是适用基准调整的情况?
罗伊·特鲁伊洛夫

2
如果将所有工作都隔离到主题分支,那么它将为重新部署奠定良好的基础。您将rebase新的更改拉到主题分支中,但是当完成该分支的更改后,您可以merge将该分支返回到主开发分支中。
redhotvengeance 2012年

1
问题是您已经发布了分支-因此您需要强制推送到存储库。您需要放弃以下两项之一:以您的方式进行发布或重新定级。抱歉。
Daniel Pittman 2012年

听起来像在这种情况下变基无效。v1.0不是主题分支,而是发行分支,因此它永远不会死,必须发布。
罗伊·特鲁伊洛夫

5

我认为,这种重基础然后强制推送模式有一个很好的用例,它不是错误推入的结果:您自己从多个位置(计算机)进行功能分支。我经常这样做,因为有时我在台式机上的办公室里工作,有时又在笔记本电脑上的家庭/客户现场工作。我偶尔需要调整基准以跟上主分支和/或使合并更整洁,但是当我离开一台机器以在另一台机器上工作时(我只是在这里拉动),我还需要强制推动。只要我是该分支机构中唯一的一名,就可以像魅力一样工作。


2
我有相同的工作流程(在多台计算机/位置工作)。因此,假设您正在开发一个名为“ mytopic”的主题分支。只要您始终将本地可丢弃的分支(仅是mytopic的一个分支)基于“ master”,然后将其合并回mytopic,那么您就不必强制推送。OP的情况略有不同,因此在类似情况下可能需要强制推动。但是,我认为OP正以错误的方式改头换面-如果他按照我的描述进行了操作,则无需强行推动。
bwv549 2015年

3

这是我使用的(假设您的分支名称为foob​​ar):

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

2
调高手看起来很奇怪。
埃米尔·维克斯特伦(EmilVikström)'02

2
git并非没有个性
放纵

1
git merge -s ours origin/<branch>是什么固定它给我们
最多

0

tl; dr与共享分支合并,对单个分支进行基础调整。--force-with-lease是用武力替代的更安全的方法,应该可以帮助您达到上述的绝境,而不会造成武力的破坏。

我见过的适用于各个团队工作流的一般经验法则是merge用于共享分支(即,母版或开发版),并rebase在自己的功能分支上使用。这是功能分支的典型生命周期

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
git rebase -i master # -i for interactive rebase allows you to squash intermediate commits
git push --force-with-lease
git merge master

我们在此处所做的操作的普通英语版本:

  1. 从master创建一个新分支
  2. 在分支上完成工作并推送到远程
  3. 从大师那里改头换面
  4. 将工作推送到远程 force-with-lease
  5. 通过非常干净的git日志合并到master,减少了来自我们共享分支的多次合并的混乱,使我们的分支与最新的master(共享分支)“追上了”

第四步非常重要,这也是我开始提倡使用rebase的主要原因之一。force-with-lease检查遥控器以查看是否已添加任何新的提交。如果您git push被证明具有破坏性,它将不会继续前进!

我希望这能给人更多使用rebase的信心。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.