如何删除旧的git历史记录?

时间:2017-01-31 08:56:24

标签: git git-rewrite-history

我有很多很多(2000+)提交的git存储库,例如:

                 l-- m -- n   
                /
a -- b -- c -- d -- e -- f -- g -- h -- i -- j -- k
                     \
                      x -- y -- z

我希望截断旧的日志历史记录 - 从(例如)commit“f”开始删除日志历史记录中的所有提交,但作为存储库的开头。

怎么做?

3 个答案:

答案 0 :(得分:32)

为了不丢失一些历史;最好先取一下你的存储库:)。我们开始:( <f>是您希望成为新的根提交的提交f的sha)

git checkout --orphan temp <f>      # checkout to the status of the git repo at commit f; creating a branch named "temp"
git commit -m "new root commit"     # create a new commit that is to be the new root commit
git rebase --onto temp <f> master   # now rebase the part of history from <f> to master onthe temp branch
git branch -D temp                  # we don't need the temp branch anymore

如果您有一个遥控器,您希望拥有相同的截断历史记录;你可以使用git push -f警告这是一个危险的命令;不要轻易使用它!如果你想确保你的代码的最后版本仍然相同;你可以运行git diff origin/master。这应该没有显示任何变化(因为只更改了历史记录;而不是文件的内容)。

git push -f  

以下两个命令是可选的 - 它们可以使您的git repo保持良好状态。

git prune --progress                 # delete all the objects w/o references
git gc --aggressive                  # aggressively collect garbage; may take a lot of time on large repos

答案 1 :(得分:11)

问题的可能解决方案由git clone使用--shallow-since选项提供。如果f之后只有少量提交,并且计算它们没有问题,那么您可以使用--depth选项。

第二个选项(--depth)仅克隆指定的分支。如果您需要其他分支,则可以将原始仓库添加为远程仓库并使用git fetch并检索它们。

如果您对结果感到满意,请删除旧存储库并重命名新存储库以替换它。如果旧存储库是远程存储库,则在删除后重新创建它并从新存储库推送到其中。

这种方法具有尺寸和速度的优点。新的repo仅包含您想要的提交,并且无需运行git prunegit gc来删除旧对象(因为它们不存在)。

答案 2 :(得分:0)

对于那些使用rebase --onto发生大量合并冲突(以及结果不正确)的人,我建议使用git filter-branch的此脚本:

#!/bin/sh

cut_sha="$1"
branch="$2"

git filter-branch \
  --parent-filter "sed -e 's/-p $cut_sha[0-9a-f]*//'" \
  --prune-empty \
  -- $branch

git for-each-ref --format='%(refname)' refs/original | \
  while read ref
  do
    git update-ref -d "$ref"
  done

git reflog expire --expire=0 --all
git repack -ad
git prune

来源:https://github.com/adrienthebo/git-tools/blob/master/git-truncate

说明:

  1. 将上面的脚本保存到本地存储库根目录(可能是git-truncate.sh)。
  2. 签出您要截断的分支(也许master)。
  3. 查看历史记录,找到要切断的第一个(最新)提交SHA(假设它是2c75a32),并确保该提交没有并行分支!
  4. 像这样运行它:$ ./git-truncate.sh 2c75a32 master
  5. (如果有遥控器,则按一下。)

重要信息:SHA必须是分支的“一部分”,并且必须是要删除的第一个提交。不要通过您要保留的第一个提交(新的“存储库开始”提交)!