简体   繁体   English

将上游更改合并到共享分支时,如何使git历史反映开发现实?

[英]How can I make git history reflective of development reality when merging upstream changes onto a shared branch?

I work with a few other developers on a fork of a popular public git repository. 我与其他一些开发人员一起使用了流行的公共git存储库。 Periodically we need to merge upstream changes into our fork. 我们需要定期将上游更改合并到我们的fork中。 How can I do this and keep the history reflective of development reality? 我该如何做到并使历史反映发展现实? For example, after I merge upstream changes, I want it to be easy for one of our developers to sync to a place on our fork which exactly reflects the state of the world N months ago when our development team was sending commits and performing tests, so we can eg run the same tests and expect the same results as they happened N months ago, and eg easily do binary searches through the history to narrow down when late-to-be-discovered bugs were introduced. 例如,在我合并上游更改之后,我希望我们的一名开发人员能够轻松地同步到叉子上的某个位置,以准确反映N个月前开发团队发送提交和执行测试时的世界状态,因此,我们可以例如运行相同的测试并期望获得与N个月前相同的结果,并且例如可以轻松地对历史记录进行二进制搜索,以缩小引入较晚发现的错误时的范围。

A few things I've tried: 我尝试过的几件事:

  1. It appears that the default git merge will end up interleaving upstream changes with our own changes, based on the dates of the commits, which then makes it near impossible to sync to a true state of the world as it happened while we were developing. 看起来,默认的git merge最终将根据提交的日期将上游的更改与我们自己的更改交织在一起,这使得在开发过程中几乎不可能同步到世界的真实状态。

  2. By using merge with --squash, the git history correctly reflects the development reality (easy to sync before and after the merge of upstream changes, and end up in same state as really happened N months ago), however it seems that --squash tells git to forget all of the individual commits, which then makes any future merging of new upstream changes extremely difficult due to gargantuan conflicts. 通过将--squash与merge一起使用,git历史记录可以正确反映开发的实际情况(易于在上游更改合并之前和之后进行同步,并且最终与N个月前的状态相同),但是--squash似乎告诉git忘记所有的单个提交,然后由于巨大的冲突使得将来任何新的上游变更的合并变得极为困难。

  3. I also tried --no-ff but that didn't seem to help at all. 我也尝试了--no-ff,但这似乎没有任何帮助。 Still get interleaving of upstream history with our history. 仍然使上游历史与我们的历史交织在一起。

Am I trying to do something that git was never intended for? 我是否在尝试做git从未打算做的事情? One strategy that may work going forward, is to merge upstream changes really often (like every day or every week), that way development reality stays extremely similar between upstream and us. 可能可行的一种策略是真正地(如每天或每周)合并上游变更,这样上游和我们之间的发展现实就保持极其相似。 But now that we've gone a few months without merging upstream, it would be nice if there's a way to essentially achieve the nice --squash behavior but without giving up git's knowledge of the individual commits. 但是既然我们已经过去了几个月没有上游合并,那么如果有一种方法可以基本上实现不错的--squash行为但又不放弃git对单个提交的知识,那将是很好的。 I considered manually doing many smaller --squash merges, like one for each ~week of upstream history. 我考虑过手动进行许多较小的壁球合并,例如上游历史记录的每〜周进行一次。 I'm guessing this will make it easier to merge future upstream changes but it's pretty painful. 我猜这将使合并将来的上游更改变得更加容易,但是这非常痛苦。 Any strong reason to do it this way or not do it this way? 是否有这样做的强烈理由? Any better ideas? 还有更好的主意吗?

Oh actually one more thought: maybe I could rebase upstream's changes onto our branch, which if I understand correctly will achieve the "reflects state of development reality" that I want (can someone confirm this to be true?), however I'd still like to squash things a bit so that my team's vastly smaller number of commits aren't overwhelmed by the upstream commits, which makes inspecting and understanding our branch history much more difficult. 哦,实际上还有一个想法:也许我可以将上游的更改基于我们的分支,如果我正确理解的话,它将实现我想要的“反映发展现实的状态”(有人可以确认这是真的吗?),但是我仍然会我想稍微压缩一些东西,以使我的团队数量很少的提交不会被上游的提交所淹没,这使得检查和了解我们的分支历史变得更加困难。 In that case, does it make sense to rebase+squash, or is there no real advantage over pure squash? 在那种情况下,重新压实+壁球是否有意义,还是与纯壁球相比没有真正的优势?

Using a rebase workflow might be what you are looking for here. 您可能正在这里使用重新设置工作流。 To understand how rebasing work, consider the following simple branch diagram: 要了解变基的工作原理,请考虑以下简单的分支图:

remote: A -- B
               \
local:           C

Here, we start with a local branch, branched off the remote, which added some new commit C , but has not yet pushed. 在这里,我们从远程分支的本地分支开始,它添加了一些新的提交C ,但尚未推送。 Of course, in reality, others on your team may be pushing new commits of their own to the remote, so let's do that too: 当然,实际上,您团队中的其他人可能正在将自己的新提交推送到远程,所以也可以这样做:

remote: A -- B -- D
               \
local:           C

Appreciate now that you can't simply push you local branch to the remote. 现在,您不能简单地将本地分支推送到远程。 One way to deal with this would be to merge the remote into your local branch. 解决此问题的一种方法是将遥控器合并到本地分支中。 But that would create a merge commit, leaving you with a non linear history that, over time, could become difficult to read. 但这会创建合并提交,从而给您留下非线性的历史记录,随着时间的推移,该历史记录可能变得难以阅读。 There is an alternative here; 这里有一个替代方案。 you may use git rebase . 您可以使用git rebase If you ran the following commands: 如果您运行以下命令:

git fetch origin
git rebase yourBranch origin/yourBranch

then you would be left with the following branch diagram: 那么您将得到以下分支图:

remote: A -- B -- D
                    \
local:                C'

In other words, your local branch would be completely linear, and you would just be able to do a simple git push to integrate your changes into the remote. 换句话说,您的本地分支将是完全线性的, 并且您只需执行简单的git push即可将您的更改集成到远程中。 Such a push would actually just be fast-forwarding the remote, laying down your new commits. 这样的推销实际上只是快进遥控器,放下您的新提交。

If you can find a way to follow a rebase workflow, then your remote branch would always be linear, and, to some extent, you would be to go back in time to any exact point in your development process. 如果您找到一种方法来遵循基础工作流,那么您的远程分支将始终是线性的,并且在某种程度上,您将使时间回到开发过程中的任何确切点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM