恐怕我找不到任何类似的场景。

我有一个有很多历史的git存储库:500多个分支,500多个标签,可以追溯到2007年年中。它包含大约19,500个提交。我们希望删除2010年1月1日之前的所有历史记录,使其更小,更容易处理(我们将在存档存储库中保留历史记录的完整副本)。

我知道我想要成为新存储库根的提交。然而,我不能找出正确的git mojo来截断回购以提交开始。我猜是某种变体

git filter-branch

涉及到移植是必要的;可能还需要分别处理我们想要保留的200多个分支中的每个分支,然后将回购补丁重新组合在一起(我确实知道如何做)。

有人做过这样的事吗?我有git 1.7.2.3,如果这很重要的话。


当前回答

作为重写历史记录的替代方法,可以考虑使用git replace,就像Pro git书籍中的这篇文章一样。讨论的示例涉及替换父提交来模拟树的开始,同时仍然将完整的历史记录作为一个单独的分支进行安全保管。

其他回答

在我的情况下,我想分成两个回购,保持历史记录,但清理日志历史从文件过滤出新的回购。

这就是解决方案:

PATHS=path_a path_b
git filter-branch -f --prune-empty --index-filter "git read-tree --empty                                                                                    
git reset \$GIT_COMMIT -- $PATHS " -- --all -- $PATHS

通过这种方式,我得到了一个具有完整提交日志历史的新回购,但仅用于我想保留的路径;

裁判:https://stackoverflow.com/a/56334887/2397613

这里有太多不是当前的答案,有些并不能完全解释后果。下面是我使用最新的git 2.26来精简历史的方法:

首先创建一个虚拟提交。此提交将作为截断后的repo中的第一个提交出现。您需要这样做是因为此提交将保存您所保存的历史记录的所有基础文件。SHA是要保留的提交的上一个提交的ID(在本例中为8365366)。字符串'Initial'将作为第一次提交的提交消息显示。如果您使用的是Windows,请从Git Bash命令提示符中输入以下命令。

# 8365366 is id of parent commit after which you want to preserve history
echo 'Initial' | git commit-tree 8365366^{tree}

上面的命令将打印SHA,例如d10f7503bc1ec9d367da15b540887730db862023。

现在只需输入:

# d10f750 is commit ID from previous command
git rebase --onto d10f750 8365366

这将首先将提交8365366的所有文件放到虚拟提交d10f750中。然后它将在d10f750顶部播放8365366之后的所有提交。最后,主分支指针将被更新到最后一次提交回放。

如果你想推这些截断的repo,只需执行git push -f。

有几件事要记住(这些适用于其他方法以及这个方法):标签不会被传输。虽然提交id和时间戳被保留,但你会看到GitHub在汇总标题中显示这些提交,比如在XY日期上的提交。

幸运的是,它是可能保持截断历史作为“存档”,以后你可以加入回切回购与存档回购。要做到这一点,请参阅本指南。

如果你想保留上游存储库的完整历史,但本地签出较小,使用git clone——depth=1 [repo]进行浅克隆。

在执行提交后,您可以执行

Git fetch——depth=1来删除旧的提交。这使得旧的提交及其对象不可访问。 Git reflog expire——expire-unreachable=now——all。使所有旧提交及其对象过期 Git gc—aggressive—prune=全部删除旧对象

参见如何在提交后删除本地git历史记录。

注意,您不能将这个“浅”存储库推到其他地方:“不允许浅更新”。在更改Git远程URL后,请参阅远程拒绝(不允许浅更新)。如果你想做到这一点,你必须坚持嫁接。

如果你想在你的git repo中释放一些空间,但不想重新构建所有的提交(rebase或graft),并且仍然能够从拥有完整repo的人那里推/拉/合并,你可以使用git clone shallow clone(——depth参数)。

; Clone the original repo into limitedRepo
git clone file:///path_to/originalRepo limitedRepo --depth=10

; Remove the original repo, to free up some space
rm -rf originalRepo
cd limitedRepo
git remote rm origin

你可以通过以下步骤来降低你现有的回购:

; Shallow to last 5 commits
git rev-parse HEAD~5 > .git/shallow

; Manually remove all other branches, tags and remotes that refers to old commits

; Prune unreachable objects
git fsck --unreachable ; Will show you the list of what will be deleted
git gc --prune=now     ; Will actually delete your data

如何删除所有git本地标签?

Ps:旧版本的git不支持从/到浅回购的克隆/推/拉。

当rebase或push到head/master时,可能会发生此错误

remote: GitLab: You are not allowed to access some of the refs!
To git@giturl:main/xyz.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@giturl:main/xyz.git'

要解决git仪表板中的这个问题,应该从“受保护的分支”中删除主分支

然后可以执行该命令

git push -f origin master

or

git rebase --onto temp $1 master