如何在使用git filter-branch后删除重复的提交?

时间:2016-12-21 15:14:35

标签: git github

我使用下面的代码编辑我的提交历史记录,错误的电子邮件设置为我的git配置,我想用正确的提交更新我的所有提交。

git filter-branch --env-filter '
WRONG_EMAIL="xxx"
NEW_NAME="xxx"
NEW_EMAIL="xxxx"

if [ "$GIT_COMMITTER_EMAIL" = "$WRONG_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$NEW_NAME"
    export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$WRONG_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$NEW_NAME"
    export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

现在问题是它复制了所有提交,甚至是那些不是我的提交,我会理解它留下了我的旧提交并创建了一个新提交,但为什么它重复提交不是我的? 任何人都可以告诉我为什么会发生这种情况以及如何解决它?

2 个答案:

答案 0 :(得分:1)

我认为问题在于你错过了以下

git push --force --tags origin 'refs/heads/*'

在本地更改提交后,您应该强制更新遥控器。

副本主要是因为遥控器上的旧提交没有改变。

答案 1 :(得分:0)

嗯,需要一点半技术背景才能完全理解这一点......

tl; dr - 如果重写提交,则还必须重写该提交的每个子项。例如,听起来你必须重写初始提交;这将强制重写每个提交。你无法解决它;这是git如何工作不可或缺的一部分。如果要更改根提交中的内容,则必须更改每次提交的哈希值。

<强>详情:

git repo中的结构相当严格;这与git如何实现其性能,使用哈希进行快速内容比较等有关。每个对象都有一个哈希值,该哈希值用于存储对象。这适用于文件(称为blob对象),目录(树对象),提交(您关注的对象)以及git可以存储和寻址的任何其他内容。

严格的算法计算哈希值,因此相同的内容将始终被赋予相同的哈希值。同样,这也是Git如何改变检测(以及其他方面)的必要条件。相反,非常不太可能两个不同的对象获得相同的哈希值(如果他们这样做会破坏你的回购)。

因此,在计算对象的哈希值时,必须考虑使对象与“另一个对象”“相同”或“与另一个对象不同”的所有事物。在提交的情况下,CommitA和CommitB可以在各方面相同,除了CommitA是CommitX的子节点且CommitB是CommitY的子节点。他们必须被视为不同的对象,否则你永远无法正确地穿越历史。

因此,当您重写Commit D的父级时,您更改了标识Commit D在历史记录中的位置的父哈希,因此您必须重写Commit D(也为其提供一个新的哈希...并且这将继续递归通过所有后代提交)。