san*_*one 2 git git-rewrite-history
这个问题似乎很奇怪,但是重写100次以上的提交后,我在同步git历史记录时遇到了问题。
在我确实重写过的机器上,一个简单的git fetch同步了所有内容。
在另一台Mac机器上,git sync没有帮助,但是在随机删除本地.git/日志和refs文件然后发出后git pull,历史记录得到了刷新。
但是,无论我在Windows计算机上做什么,都无法刷新项目历史记录。尝试了所有:
git reset --hard HEAD 和 git fetchgit fetch --allgit pull每次在Windows计算机上,我都会获得与另一作者相同的提交的重复条目(更改了Author字段)。
我使用本教程重写了大量历史记录:
https://help.github.com/articles/changing-author-info/
Open Terminal.
Create a fresh, bare clone of your repository:
git clone --bare https://github.com/user/repo.git
cd repo.git
Copy and paste the script, replacing the following variables based on the information you gathered:
OLD_EMAIL
CORRECT_NAME
CORRECT_EMAIL
#!/bin/sh
git filter-branch --env-filter '
OLD_EMAIL="your-old-email@example.com"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="your-correct-email@example.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_NAME="$CORRECT_NAME"
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
view rawgit-author-rewrite.sh hosted with ? by GitHub
Press Enter to run the script.
Review the new Git history for errors.
Push the corrected history to GitHub:
git push --force --tags origin 'refs/heads/*'
Clean up the temporary clone:
cd ..
rm -rf repo.git
Run Code Online (Sandbox Code Playgroud)
有没有人经历过大量的git历史重写?如果是,其他团队成员刷新其git历史记录的步骤是什么?
理解这里问题的关键是在Git中:
当你“改写历史”,你没有,你能不能,改变任何现有的承诺。而是,您复制每个现有的提交。什么git filter-branch确实是复制所有您请求的提交,在“最老”(最原始的),以“最新”(至少祖/尖大多数)命令,应用过滤器,因为它有云:
最后,这意味着真正进行大规模重写,实际上是您并排放置了两个不同的存储库:旧的存储库及其旧的提交,而新的存储库具有新的提交。在筛选过程结束时,git filter-branch更改名称以指向新副本。
如果您有一个只有三个提交的小型存储库(我们称它们为A通过C一个master分支提交)和一个分支,并且所有三个提交都需要进行一些更改,那么您将获得以下信息:
A--B--C [was the original master]
A'-B'-C' <-- master
Run Code Online (Sandbox Code Playgroud)
从字面上看,新提交是新提交。任何仍在使用旧提交的人实际上仍在使用旧提交。他们必须停止使用这些提交并开始使用新的提交。
在某些情况下,您git filter-branch最终指定的过滤器在原始提交中根本不会更改任何内容。在这种情况下,如果写入的新提交filter-branch与原始提交逐位相同,则只有在那时,新提交才与旧提交实际上相同。如果我们查看相同的三提交原始存储库,但选择仅修改第二次B提交的内容或元数据的过滤器,则会得到:
A--B--C
\
B'-C' <-- master
Run Code Online (Sandbox Code Playgroud)
作为最终结果。
请注意,即使C过滤未更改原始内容,也会发生这种情况。这是因为有关原始的某些内容B 已更改,导致提交了新的和不同的提交B'。因此,在git filter-branch复制时C,它必须进行一项更改:副本的父项C'是新的,B'而不是原始的B。
也就是说,已git filter-branch复制A到新的提交,但根本没有任何更改(甚至没有更改任何父信息),因此,新的提交原来是对original的重用A。然后将其复制B到新提交,并进行更改,因此新提交现在为B'。然后,它进行了复制C而不进行更改,将父级更改为B',并编写了新的commit C'。
如果您的过滤器所做的更改只是C,该git filter-branch命令将复制A到自身,B对自身,C对C',赠送:
A--B--C
\
C' <-- master
Run Code Online (Sandbox Code Playgroud)
通常,人们处理大量上游origin重写的最简单方法是让他们完全丢弃其现有存储库。也就是说,我们希望共享的原始提交不超过几个:在大规模重写的某个早期阶段,我们更改提交A或在其附近进行一次提交,因此每个后续提交都必须复制到一个新提交中。因此,创建新克隆可能比更新现有克隆昂贵得多。这当然更容易!
严格来讲,这不是必需的。作为“下游”使用者,我们可以运行git fetch并获取具有其更新的分支名称以及更新的标记的所有新提交(此处特别小心,因为标记默认情况下不会更新)。但是由于我们有自己的分支名称,指向原始提交而不是新复制的提交,因此我们现在必须使我们的每个分支名称都引用新复制的提交,也许还复制上游拥有的所有提交没有(因此尚未复制)。
换句话说,对于每个分支,我们都可以运行:
git checkout <branch>
git reset --hard origin/<branch>
Run Code Online (Sandbox Code Playgroud)
使我们的branch名称(作为其最先提交)与该名称相同。(请记住,强制更新我们的所有名称,以匹配指向的哈希ID 。)origin/branchgit fetch origin/branchbranchorigin
这等效于删除我们的每个分支并使用git checkout它们来重新创建它们。换句话说,它不会继承我们所做的任何改写的origin人都不会复制的承诺(因为他们不能这样做是因为他们没有它们)。为了落实我们的承诺,我们必须做与上游上游基地相同的工作。内置的分叉点代码是否会为您正确地做到这一点(如果您的Git至少为2.0,那么通常会做到)确实是针对一个单独的问题(并且已经在其他地方得到了回答)。 请注意,您必须对您希望继续提交的每个分支执行此操作。
| 归档时间: |
|
| 查看次数: |
1700 次 |
| 最近记录: |