2015-06-20 103 views
5

我试图压扁许多提交到一个单一的问题是,我需要做的作者(姓名或电子邮件)。Git Squash按作者 - 所有作者提交到一个提交

的情况:

可以说我有一个分支叫功能一,在这个部门我有很多很多的作者提交。如何将作者的所有提交(例如电子邮件)压缩为单个提交。我想这样做是为了能够将所有作者提交合并到master中。

这里有什么帮助吗?

在此先感谢

+0

听起来好像它会导致大量不必要的工作。也就是说,如果特定作者的提交不是连续的,那么压缩它们将需要大量的手动干预。你最好让你的许多作者各自在自己的分支上工作。 – larsks

回答

1

Be careful rewriting history

最终的结果你想可能是可能的,如果你对每个作者创建分支,cherry-pick从每个作者适当的分支的提交,然后压扁这些变化。但是,如果这些提交有意义地相互依赖,我认为这不会起作用。

如果你有一系列提交:

  Author1    Author2    Author1 
version1 ---commit---> version2 ---commit---> version3 ---commit--->... 

如果你尝试从中提取Author2的变化,并将其应用于版本1,有一个很好的机会,它将没有任何意义(例如,如果Author2修改Author1创建的代码)。

1

考虑到Kenkroncaveats,你可以做:

SORTED_GIT_LOGS=$(git log --pretty="format:%an %H" master..feature_a | sort -g | cut -d' ' -f2); \ 
IFS=$(echo -en "\n\b"); for LOG in $SORTED_GIT_LOGS; do \ 
    git cherry-pick $LOG; \ 
done | less 

git log --pretty="format:%an %H" master..feature_a | sort -g将在feature_a提交(不是那些从master因为master..feature_a语法)

的日志分类您仍然需要进行交互式重新分版来压扁master(现在由作者订购)提交。

+0

交互式底座示例:http://denniskubes.com/2012/08/22/honey-i-squashed-the-commits/ – VonC

+0

如果作者完成,'git reset'也可以工作:http:// makandracards .com/makandra/527-squash-several-git-commits-into-a-single-commit – VonC

1

我需要在回收处于脱机状态时对不必要的大型存储库进行类似的重写。我采用的方法是使用GIT_SEQUENCE_EDITOR尝试自动“交互式”rebase,this answer由@ james-foucar & @pfalcon覆盖。

为了更好地工作,我发现最好先从被重写的历史记录中删除合并。对于我自己的情况,这是使用大量的git rebase --onto完成的,这在StackOverflow的其他问题中得到了充分的说明。

我创建了一个small script generate-similiar-commit-squashes.sh生成pick & squash命令,这样连续的相似提交会被压扁。我使用author-date-and-shortlog来匹配类似的提交,但你只需要作者(我的要点有关如何使其仅匹配作者的评论)。

$ generate-similiar-commit-squashes.sh > /tmp/git-rebase-todo-list 

输出看起来与同风格的“更新XYZ”提交信息像

... 
pick aaff1c556004539a54a7a33ce2fb859af0c4238c [email protected] 
squash aa190ea2323ece42f1cd212041bf61b94d751d5c [email protected] 
pick aab8c98981a8d824d2bc0d5278d59bc1a22cc7b0 [email protected]_config.yml 

的仓库也充满了自我恢复。当被压扁时,他们导致空的承诺。

我正在合并的提交具有相同的提交消息。 git rebase -i提供了修改后的提交消息,并附加了所有压缩的提交消息,这些消息将会重复。为了解决这个问题,我使用了一个来自this answer的小Perl脚本来删除git rebase提供的提交消息中的重复行。它在文件中更好,因为它将用在shell变量中。

$ echo 'print if ! $x{$_}++' > /tmp/strip-seen-lines.pl 

现在的最后一步:

$ GIT_EDITOR='perl -i -n -f /tmp/strip-seen-lines.pl ' \ 
    GIT_SEQUENCE_EDITOR='cat /tmp/git-rebase-todo-list >' \ 
    git rebase --keep-empty -i $(git rev-list --max-parents=0 HEAD) 

尽管使用--keep-emptygit通过关于空提交这个过程中抱怨几次。它会将我倾倒到控制台上,但不完整git rebase。为了跳过空的提交并恢复处理,需要以下两个命令(在我的情况下相当频繁)。

$ git reset HEAD^ 
$ GIT_EDITOR='perl -i -n -f /tmp/strip-seen-lines.pl ' git rebase --continue 

再次尽管--keep-empty,我发现我在最后提交历史had no empty commits,所以上面的重置已经删除它们。我认为我的git版本2.14.1有问题。处理~100万次这样的提交在蹩脚的笔记本电脑上花了超过10分钟。

+0

有趣的方法,比我的答案更完整。 +1。不知道你的'--keep-empty'问题。 – VonC

+0

重写历史记录也值得注意,如果您不希望重写过程将您自己(重写器)作为每次提交的提交者,您可能需要通过重置提交者来完成重写。最简单的方法是[设置提交者=作者](https://stackoverflow.com/a/32944640/5037965),但如果原始提交者信息实际上很重要并且需要保留,则需要更详细的方法。 –

+0

我已经添加到https://gist.github.com/jayvdb/9b41677f00065dbd94cc02446fc5ba34一个脚本'generate-multiple-new-file-squashes.sh'来合并仅包含连续添加的提交(即提交者使用GitHub/GitLab/BitBucket Web UI“上传文件”) –