2

有一个简单app的完整源代码,需要根据它制作教材。所以,我在想,从完整的源代码初始化一个 git 存储库,然后开始以相反的顺序简化和删除部分,并提交每个后续更简单的工作版本,直到只有一个“你好,世界!” 遗迹。

问题:如何在 git 存储库中反转提交,保留提交消息等,使其看起来像最初按此顺序提交?

可以使用任何其他 VCS 来完成简化部分,只要最终结果是 git repo。

4

4 回答 4

2

我会使用git format-patch将补丁放入文件中,按时间顺序对它们进行排序(编号文件名,然后sort -r是 ),并使用git apply --reverse. 然后我会使用交互式 rebase ( -i) 来修复细节并提交消息。

无论如何,git 是很好的工具,因为您可以轻松地操纵历史,但这需要一些工作。

编辑:

当我稍后看到这个时,我对如何做到这一点有了更好的想法。它不改变基本原理,只改变实现:

我希望,您在主分支中有一些历史记录的存储库。因此,在当前 HEAD上镜像提交的最简单方法是:

git checkout -b mirror
git log --format=%H | xargs -n 1 git revert

现在您在 master 分支中有旧的历史记录,并且 master 和 mirror 之间的新提交是来自 master 的反向提交。就像照镜子一样。我猜你会想要删除旧的历史并编辑提交消息,所以玩得开心git rebase -i

于 2013-02-03T13:15:46.910 回答
2

我编写了一个脚本“git-reverse.sh”,它完全反转了 git repo 的所有分支。

它使用组合git log --pretty="%T"来提取树哈希,并git commit-tree针对原始树对象(文件)创建新的提交对象,但父边缘反转。

它似乎被一些回购卡住了。我不知道为什么。

你可以在这里找到它:

https://github.com/gsylvie/git-reverse.sh

示例用法

git clone --mirror [git-clone-url]
cd [repo.git]
./git-reverse.sh
git log --all --date-order --graph --decorate

示例输出

$ ./git-reverse.sh 
be0923ece8f73281e5e54906c29debb852894b92 - Reversed 1 of 360 (0%)
061bca59b29e75becbde66d2e510fc2b4059ccb2 - Reversed 2 of 360 (0%)
6a19039e05e3a0186187d0a6943634e8499b5a65 - Reversed 3 of 360 (0%)
7afe25e8caf93eb7107471a1bd078d4adc3f6999 - Reversed 4 of 360 (1%)
8b556f6fe97c5357c2328467a5ba01b77931ff82 - Reversed 5 of 360 (1%)
71fd0883975154f48059ca929db8ccb659c5049a - Reversed 6 of 360 (1%)
[etc...]
Switched to branch 'master'
Your branch and 'origin/master' have diverged,
and have 199 and 159 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

*********************************************
| Git repo successfully reversed!!! :-) (-: |
*********************************************
To push the reversed repo:
  rm .git/packed-refs
  rm -rf .git/refs/remotes
  git push --mirror [new-git-clone-url]  

WARNING:
========
Pushing a reversed git repo is a profoundly destructive and confusing operation.

You have a full 'git clone --mirror' backup stored somewhere safe, right?
于 2017-04-01T22:05:34.223 回答
1

如果存储库中的提交数量有限(我认为在制作教材时就是这种情况),我认为您可以简单地手动以相反的顺序执行樱桃挑选。

A <- B <- C <- D <- E
                    ^HEAD

假设 A 是第一个空的提交,而 B 是完整的文件集,CDE 正在逐步删除文件,我认为你可以从 A 的另一个分支开始

A <- B <- C <- D <- E
^NewHead            ^HEAD

和樱桃挑选 E、D、C、B 到 New Head:

A <- B <- C <- D <- E
 ^                  ^HEAD
  \- E' <- D' <- C' <- B'
                       ^NewHead

当然,如果确实有很多提交,那么在导入之前导出补丁并使用脚本来操作它们(如其他答案所建议的那样)可能是更好的选择

于 2013-02-04T05:01:46.447 回答
0

首先,我不明白您为什么需要更改提交。您可以按任何顺序签出相应的版本。即git checkout master~1,显示,git checkout master~2显示,等等。

如果您确实需要它来获取您的历史记录,请尝试使用revertwhich replays history back。例如git revert HEAD~5..HEAD,将以相反的顺序恢复最后 5 次提交。但是,它会生成提交消息来说明它是Revert "old commit message". 但是您可以编写脚本来修改消息。

于 2013-02-04T09:52:19.683 回答