简体   繁体   English

合并后的Git壁球历史

[英]Git squash history after merge

I merged an upstream of a large project with my local git repo. 我将一个大型项目的上游与我当地的git repo合并。 Prior to the merge I had a small amount of history that was easy to read through, but after the merge a massive amount of history is now in my repo. 在合并之前,我有一些易于阅读的历史,但在合并之后,我的回购中有大量的历史记录。 I have no need for all the history commits from the upstream repo. 我不需要上游回购的所有历史提交。

There have been other commits made after this upstream merge that I would like to keep. 在我想保留的上游合并之后还有其他提交。 How do I squash all that history that was merged from the upstream into one commit while keeping the commits made after the upstream merge? 如何在保持上游合并之后的提交的同时,将从上游合并的所有历史记录压缩到一个提交中?

The solution I ended up using was to manually recreate the history. 我最终使用的解决方案是手动重新创建历史记录。 I did this mainly because I didn't want to spend too much time looking for an elegant solution and there wasn't that much history (around 30 commits I'd have to manually merge). 我这样做主要是因为我不想花太多时间寻找一个优雅的解决方案而且没有那么多的历史(大约30次提交我必须手动合并)。

So, I created a branch before I merged the huge upstream: 所以,在合并庞大的上游之前,我创建了一个分支:

git checkout -b remove-history-fix <commit ID before merge>

Then re-merged the upstream using the --squash option. 然后使用--squash选项重新合并上游。

git merge --squash <upstream tag>

Then manually cherry-picked the commits after the merge from the old branch (the one with the huge amount of upstream history). 然后从旧分支(具有大量上游历史记录的分支)合并之后手动挑选提交。

git cherry-pick <commit ID>

After all those commits were merged into my remove-history-fix branch, I removed the branch with the upstream history. 在所有这些提交合并到我的remove-history-fix分支之后,我删除了具有上游历史记录的分支。

git branch -D <upstream-history-branch>

I was able to squash several commits after multiple merges from the master branch using the strategy found here: https://stackoverflow.com/a/17141512/1388104 使用此处的策略,我可以在从主分支进行多次合并后压缩多次提交: https//stackoverflow.com/a/17141512/1388104

git checkout my-branch            # The branch you want to squash
git branch -m my-branch-old       # Change the name to something old
git checkout master               # Checkout the master branch
git checkout -b my-branch         # Create a new branch
git merge --squash my-branch-old  # Get all the changes from your old branch
git commit                        # Create one new commit

You will have to force an update if you need to push your squashed branch to a remote repository that you have previously pushed to, eg git push origin my-branch -f 如果您需要将压扁的分支推送到之前推送到的远程存储库,则必须强制更新,例如git push origin my-branch -f

A couple of options for you: 有几种选择:

Limit Logging 限制记录

Not exactly what you asked for, but possibly a good alternative, and a lot easier. 不完全是你要求的,但可能是一个很好的选择,而且更容易。 This allows you to use git like normal, but hides all the stuff you don't want to see (assuming the issue is the history cluttering up your log and not the raw storage space. I think squashing the merge in your branch won't prevent git from including all the commits from upstream if you fetched the upstream for the merge action in the first place.). 这允许你像正常一样使用git,但是隐藏了你不想看到的所有内容(假设问题是历史混乱你的日志而不是原始存储空间。我认为压缩你的分支中的合并不会如果您首先在上游获取合并操作,则阻止git包含来自上游的所有提交。)。

In this case, you would do a normal merge, but when logging you would add --first-parent to the command. 在这种情况下,您将执行常规合并,但在进行日志记录时,您将向命令添加--first-parent

For example, without the option I might have (assume "sample more" 1 to 3 was actually a lot more commits) 例如,没有我可能有的选项(假设“样本更多”1到3实际上是更多提交)

$ git log --oneline
0e151bf Merge remote-tracking branch 'origin/master' into nosquash
f578cbb sample more 3
7bc88cf sample more 2
682b412 sample more 1
fc6e1b3 Merge remote-tracking branch 'origin/master'
29ed293 More stuff
9577f30 my local change
018cb03 Another commit
a5166b1 Initial

But, if I add --first-parent it cleans up to this: 但是,如果我添加--first-parent它会清除这个:

$ git log --oneline --first-parent
0e151bf Merge remote-tracking branch 'origin/master'
fc6e1b3 Merge remote-tracking branch 'origin/master'
9577f30 my local change
018cb03 Another commit
a5166b1 Initial

Notice all of the commits from the master after I branched ("my local change" being my divergent commit) are gone. 注意我分支后的所有提交(“我的本地更改”是我的分歧提交)都消失了。 Only commits I made show up, including when I merged. 只有我提交的提交,包括合并时。 If I had used better commit messages during the merge, I might even know what the batch of changes were. 如果我在合并期间使用了更好的提交消息,我甚至可能知道一批更改是什么。

Replace History 替换历史

This is for what you asked. 这是你提出的问题。

Taking inspiration from https://git-scm.com/book/en/v2/Git-Tools-Replace https://git-scm.com/book/en/v2/Git-Tools-Replace获取灵感

What we'll do here is squash the remote's history, replace their history with our squashed version from our perspective, and merge the squashed version. 我们在这里要做的就是压缩遥控器的历史,用我们的视角用我们压扁的版本替换他们的历史,然后合并压缩的版本。

In my example repository, the revisions that upstream added which I hadn't merged yet were 682b412 "sample more 1" to origin/master (f578cbb "sample more 3") (although not that long for this example, pretend there are 50 commits or whatever in between). 在我的示例存储库中,上游添加的尚未合并的修订版本是682b412“示例更多1”到origin / master(f578cbb“示例更多3”)(虽然这个示例没那么长,假装有50个提交或者其中的任何东西)。

The first thing I want is a local branch of the remote side: 我想要的第一件事是远程端的本地分支:

git checkout -b squashing origin/master

Next, I want to quickly squash it 接下来,我想快速压制它

git reset --soft 682b412~
git commit -m "Squashed upstream"

Note the tilde ~ character. 注意代字号~字符。 That causes our branch to be at the parent of the first commit in the range we want to squash, and because we specified --soft , our index is still at the last commit in the range we want to squash. 这导致我们的分支位于我们想要--soft范围内的第一个提交的父级,并且因为我们指定了--soft ,我们的索引仍然是我们想要--soft范围内的最后一次提交。 The commit line results in a single commit that consists of what was our first through last, inclusive. 提交行导致单个提交,包括我们的第一个到最后一个包含的内容。

At this point, the origin/master and squashing branches have identical tree contents but different histories. 此时,origin / master和squashing branches具有相同的树内容但历史不同。

Now, we tell git that when it sees references to the original commit of origin/master, to use our squashed commit instead. 现在,我们告诉git当它看到对origin / master的原始提交的引用时,使用我们的压缩提交。 Using git log I can see the new "Squashed upstream" commit is 1f0bc14, so we do: 使用git log我可以看到新的“Squashed upstream”提交是1f0bc14,所以我们这样做:

git replace f578cbb 1f0bc14

From here on, your git will use the "squashed upstream" commit. 从这里开始,你的git将使用“压缩上游”提交。

Back on our original branch (if it was "master") 回到原来的分支(如果是“主人”)

git checkout master
git merge f578cbb

This appears to merge the origin master (f578cbb), actually gets 1f0bc14's contents, but logs it as having a parent SHA1 of f578cbb 这似乎合并了原始主文件(f578cbb),实际上获得了1f0bc14的内容,但是将其记录为具有f578cbb的父SHA1

We no longer need the squashing branch, so you can get rid of it. 我们不再需要挤压分支,所以你可以摆脱它。

Now, let's say upstream added more features. 现在,让我们说上游添加了更多功能。 In this simple example, on upstream's repo, a log might show this: 在这个简单的例子中,在上游的repo上,日志可能会显示:

84f5044 new feature
f578cbb sample more 3
7bc88cf sample more 2
682b412 sample more 1
29ed293 More stuff
018cb03 Another commit
a5166b1 Initia

After we fetch upstream though, if we look at its log from our repo, we see this instead: 在我们获取上游之后,如果我们从我们的仓库查看其日志,我们会看到:

84f5044 new feature
f578cbb squashed upstream
29ed293 More stuff
018cb03 Another commit
a5166b1 Initial

Note how it appears to have squashed history to us as well, and more importantly, the squashed upstream SHA1 is showing the one used in upstream's history (for them it is really the "sample more 3" commit). 注意它似乎也给我们带来了压扁历史,更重要的是,压扁的上游SHA1显示了上游历史中使用的那个(对于它们来说,它实际上是“示例更多3”提交)。

So, merging continues to work like normal 因此,合并继续像平常一样工作

git merge origin/master

But we don't have such a cluttered log: 但是我们没有这样凌乱的日志:

4a9b5b7 Merge remote-tracking branch 'origin/master' for new feature
46843b5 Merge remote-tracking branch 'origin/master'
84f5044 new feature
f578cbb squashed upstream
fc6e1b3 Merge remote-tracking branch 'origin/master'
29ed293 More stuff
9577f30 my local change
018cb03 Another commit
a5166b1 Initial

If the "new feature" commit in upstream was similarly a large number of commits, we could repeat this process to squash that down as well. 如果上游的“新功能”提交同样是大量的提交,我们可以重复这个过程来压缩它。

There is no way to do it, as you won't be able to push back or merge again with that remote repository or any other of that same project. 没有办法做到这一点,因为您将无法再次向后推送或与该远程存储库或任何其他同一项目合并。 When squashing, you are changing history, resulting in different sha1-hashes between your repository and the remote one. 压缩时,您正在更改历史记录,从而导致存储库与远程存储库之间出现不同的sha1-hash。

You'll have to live with the large history. 你将不得不忍受大历史。

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

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