Git按作者压缩-所有作者提交到单个提交中

Git按作者压缩-所有作者提交到单个提交中,git,git-rebase,Git,Git Rebase,我正在尝试将许多提交压缩成一个提交,问题是我需要通过作者(姓名或电子邮件)来完成 本案: 假设我有一个名为feature-a的分支,在这个分支中,我有许多提交给许多作者。如何将作者提交的所有内容(例如电子邮件)压缩为单个提交。我想这样做是为了能够合并所有作者提交到主 有人帮忙吗 提前感谢 如果您为每个作者创建分支,将每个作者提交到正确的分支中,然后挤压这些更改,那么您想要的最终结果可能是可能的。然而,我认为,如果这些承诺有意义地相互依赖,那么这将不起作用 如果您有一系列提交:

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

本案:

假设我有一个名为feature-a的分支,在这个分支中,我有许多提交给许多作者。如何将作者提交的所有内容(例如电子邮件)压缩为单个提交。我想这样做是为了能够合并所有作者提交到主

有人帮忙吗

提前感谢

如果您为每个作者创建分支,将每个作者提交到正确的分支中,然后挤压这些更改,那么您想要的最终结果可能是可能的。然而,我认为,如果这些承诺有意义地相互依赖,那么这将不起作用

如果您有一系列提交:

            Author1                Author2                Author1
version1 ---commit---> version2 ---commit---> version3 ---commit--->...
如果您试图从Author2中提取更改,并将其应用于version1,则很可能没有意义(例如,如果Author2修改Author1创建的代码)。

考虑到,您可以执行以下操作:

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..feature_a
语法的原因,不是来自
master
的日志)


您仍然需要在
master

上执行交互式重基来挤压(现在由作者排序)提交。我需要在repo脱机时在不必要的大型存储库上执行类似的重写。我采用的方法是使用@james foucar和@pfalcon中介绍的
GIT_SEQUENCE_编辑器
尝试自动“交互式”重基

为了让它正常工作,我发现最好先从正在重写的历史部分删除合并。在我自己的例子中,这是使用大量的
git-rebase--on
实现的,这在StackOverflow的其他问题中有详细介绍

我创建了一个函数来生成
pick
&
squash
命令,以便压缩连续的类似提交。我使用author date和shortlog来匹配类似的提交,但您只需要author(我的要点是如何使其仅与author匹配)

输出看起来像

...
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
存储库中还充满了具有相同样式“Update xyz”提交消息的自恢复。挤压时,它们会导致空提交

我正在合并的提交具有相同的提交消息
git-rebase-i
提供了一个修改后的提交消息,其中附加了所有压缩的提交消息,这是重复的。为了解决这个问题,我从中使用了一个小的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
将我转储到控制台。要跳过空提交和恢复处理,需要以下两个命令(在我的例子中非常频繁)


尽管
--keep empty
,我还是在最终的git历史记录中找到了I,因此上面的重置将它们全部删除。我认为我的git版本2.14.1有问题。在一台蹩脚的笔记本电脑上处理约10000次这样的提交只需10分钟。

这听起来可能会导致很多不必要的工作。也就是说,如果特定作者的提交不是连续的,那么挤压它们将需要大量的手动干预。你最好让你的许多作者都在他们自己的分支上工作。交互式重基示例:如果由作者完成,git reset也可以工作:
git-reset
:有趣的方法,比我的答案更完整+1.不确定您的<代码>--但是保持空问题。同样值得注意的是,任何时候重写历史记录时,如果您不希望重写过程将您自己(重写者)作为每次提交的提交者,您可能需要通过重置提交者来完成重写。最简单的方法是,但如果原始提交者信息实际上很重要并且需要保留,则需要更详细的方法。我已添加到脚本
生成多个新文件压缩。sh
以合并仅包含连续添加的提交(即提交者使用GitHub/GitLab/BitBucket Web UI)“上载文件”)如果需要访问第一次提交,请使用
git-rebase-i--root
$ 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)
$ git reset HEAD^
$ GIT_EDITOR='perl -i -n -f /tmp/strip-seen-lines.pl ' git rebase --continue