作者Git Squash - 所有作者都提交到一个提交

时间:2015-06-20 00:26:08

标签: git git-rebase

我正在尝试将许多提交压缩成一个,问题是我需要通过作者(名称或电子邮件)来做。

案例:

假设我有一个名为feature-a的分支,在这个分支中我有很多作者的提交。如何将作者(例如电子邮件)的所有提交压缩到一个提交中。我希望这样做能够将所有作者提交合并到master。

这里有任何帮助吗?

提前致谢

3 个答案:

答案 0 :(得分:1)

Be careful rewriting history

如果为每个作者创建分支,cherry-pick从每个作者提交到正确的分支,然后压缩这些更改,则可能会出现所需的最终结果。但是,如果这些提交有意义地相互依赖,我认为这不会起作用。

如果您有一系列提交:

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

如果您尝试从Author2中提取更改并将其应用于版本1,则很可能没有意义(例如,如果Author2修改了Author1创建的代码)。

答案 1 :(得分: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语法)

你仍然需要做一个交互式的rebase来压缩master上的(现在按作者排序)提交。

答案 2 :(得分:1)

我需要在repo离线时对不必要的大型存储库进行类似的重写。我采用的方法是使用GIT_SEQUENCE_EDITOR尝试自动化的“交互式”变基,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

输出看起来像

...
pick aaff1c556004539a54a7a33ce2fb859af0c4238c foo@example.com-2015-01-01-Update-head.html
squash aa190ea2323ece42f1cd212041bf61b94d751d5c foo@example.com-2015-01-01-Update-head.html
pick aab8c98981a8d824d2bc0d5278d59bc1a22cc7b0 foo2@example.com-2015-01-28-Update-_config.yml

存储库也充满了自我还原,具有相同样式的“更新xyz”提交消息。当被压扁时,它们会导致空提交。

我合并的提交有相同的提交消息。 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-empty,但git在此过程中多次抱怨空提交。它会把我带到一个不完整的git rebase的控制台。要跳过空提交和恢复处理,需要以下两个命令(在我的情况下经常使用)。

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

尽管--keep-empty,我在最后的git历史记录中找到了had no empty commits,所以上面的重置已将它们全部删除了。我认为我的git版本2.14.1有问题。处理~10000这样的提交在一台糟糕的笔记本电脑上花了10多分钟。