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

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

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

git filter-branch

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

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


当前回答

注意:为了支持git替换,这个已经被弃用了。

你可以将你的新根提交的父节点移植到没有父节点的节点上(或者移植到一个空的节点上,例如你的存储库的真正根节点上)。例如:echo "<NEW-ROOT-SHA1>" > .git/info/graft

在创建嫁接后,它立即生效;你应该可以查看git日志,看到不想要的旧提交已经消失了:

$ echo 4a46bc886318679d8b15e05aea40b83ff6c3bd47 > .git/info/grafts
$ git log --decorate | tail --lines=11
commit cb3da2d4d8c3378919844b29e815bfd5fdc0210c
Author: Your Name <your.email@example.com>
Date:   Fri May 24 14:04:10 2013 +0200

    Another message
 
commit 4a46bc886318679d8b15e05aea40b83ff6c3bd47 (grafted)
Author: Your Name <your.email@example.com>
Date:   Thu May 23 22:27:48 2013 +0200

    Some message

如果一切看起来都像预期的那样,您可以使用git filter-branch -- --all将其永久化。

注意:在执行过滤分支步骤之后,所有的提交id都将发生变化,因此任何使用旧回购的人都不能与使用新回购的人合并。

其他回答

对于先前使用——depth克隆的现有存储库

git clone --depth=1 ...

只做

git pull --depth=1 --update-shallow

https://git-scm.com/docs/git-pull

注意:为了支持git替换,这个已经被弃用了。

你可以将你的新根提交的父节点移植到没有父节点的节点上(或者移植到一个空的节点上,例如你的存储库的真正根节点上)。例如:echo "<NEW-ROOT-SHA1>" > .git/info/graft

在创建嫁接后,它立即生效;你应该可以查看git日志,看到不想要的旧提交已经消失了:

$ echo 4a46bc886318679d8b15e05aea40b83ff6c3bd47 > .git/info/grafts
$ git log --decorate | tail --lines=11
commit cb3da2d4d8c3378919844b29e815bfd5fdc0210c
Author: Your Name <your.email@example.com>
Date:   Fri May 24 14:04:10 2013 +0200

    Another message
 
commit 4a46bc886318679d8b15e05aea40b83ff6c3bd47 (grafted)
Author: Your Name <your.email@example.com>
Date:   Thu May 23 22:27:48 2013 +0200

    Some message

如果一切看起来都像预期的那样,您可以使用git filter-branch -- --all将其永久化。

注意:在执行过滤分支步骤之后,所有的提交id都将发生变化,因此任何使用旧回购的人都不能与使用新回购的人合并。

当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

如何截断git历史记录:

#!/bin/bash
git checkout --orphan temp $1
git commit -m "Truncated history"
git rebase --onto temp $1 master
git branch -D temp

Here $1 is SHA-1 of the commit you want to keep and the script will create new branch that contains all commits between $1 and master and all the older history is dropped. Note that this simple script assumes that you do not have existing branch called temp. Also note that this script does not clear the git data for old history. Run git gc --prune=all && git repack -a -f -F -d after you've verified that you truly want to lose all history. You may also need rebase --preserve-merges but be warned that the git implementation of that feature is not perfect. Inspect the results manually if you use that.

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

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

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

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

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