只保留最后三个git提交。完全删除其他所有内容

时间:2015-11-10 03:45:00

标签: git

下面是git历史记录树,其中突出显示了我要保留的三个提交。我怎样才能让其他一切从字面上消失,好像它们从未存在过一样?

Branches and merges and sh*t

我尝试使用here的答案,但我不断得到以下内容:

fatal: Needed a single revision
Does not point to a valid commit: e147db0477dbb21e74615f4bfff06378b7d269c8^

2 个答案:

答案 0 :(得分:2)

三个突出显示的提交中的第一个是合并。如果你保留它,你必须(真的,它不是一个选项)保留你不想要的5个提交。 (浅层克隆可以在深化之前省略它们,但它们在逻辑上仍然存在,即使不是物理存在的。)

因此,你需要做的是做一个新的提交,你可以指向masterorigin/master,即"为好"作为合并,但本身并不是合并,只是将三个提交中间保留为其父级。

"清理"和"前端抛光"提交可以保持原样;他们只需要一个指向它们的新提交,它使用与合并相同的。 (您也可以保留原始提交消息,或者创建一个新消息。)Git是git,有很多方法可以实现这一点。最少的命令方法是使用git commit-tree 1 ,但让我们看一个我认为更简单易懂的方法。

首先,我们首先创建一个新的分支,指向第二个to-keep commit," frontend polish"一。 (这也假设当前的工作树是干净的。)

$ git branch newmaster master^2   # master^ if 1st parent 
$ git checkout newmaster

现在我们想要使用与合并一起存储的源树进行新的提交,这本身不是合并。我们首先擦除所有内容(以便在合并期间删除任何文件,在我们完成后仍然删除 - 如果您确定没有删除任何内容,则可以跳过此步骤)。然后,我们检查与master上的最新提交相关联的所有文件,即合并结果。这假设您处于顶级目录:

$ git rm -r .               # empties work-tree and index
$ git checkout master -- .  # repopulates work-tree and index

这种形式的checkout摘自给定的提交(master最常提交)给定的路径 - 在这种情况下,.,是存储库的顶级,因此包括提交中的每个路径。在提取过程中,每个提取的文件也会输入到索引中,因此我们现在可以准备好新的提交了。

如果需要,唯一要做的就是恢复合并消息:

$ git log -1 master > /tmp/msg

(或类似),然后:

$ git commit

这会在newmaster上进行新的提交,其父级是"前端打磨"提交,其父母是"清理",没有更多的父母。现在你只需要将其作为分支master,这非常简单:

$ git branch -D master   # forcibly discard old master entirely
$ git branch -m master   # rename newmaster to master

此时您可以强制推送到origin以替换服务器上的master(但请确保共享服务器版本的所有人都可以使用此功能,并且有没有新的提交在那里担心)。当服务器master更新后,您的origin/master(从服务器复制回来)将再次指向您的master(此时您可以设置您的主人&#39} ;像往常一样上游到origin/master

作为参考,这只需要2到4个git命令,具体取决于你想要保留多少,你想从头开始写多少,以及你如何计算命令:

$ git log -1 --format=%B master > /tmp/logmsg

(现在根据需要编辑/tmp/logmsg

$ newid=$(git commit-tree -p master^{tree} < /tmp/logmsg)

(此时,请确保其有效,例如git show $newid

$ git update-ref -m "reset to new non-merge tip" master $newid

(现在你有master指向只有一个父项的新复制提交。

答案 1 :(得分:0)

尽管有一个古老的问题并得到了充分回答,但这是另一个可能的选择。一个小脚本,如果从您要保留的历史记录的存储库部分中调用该脚本,则会创建一个tmp目录并浅克隆原始存储库的内容。

DEEP_REPO=$(git rev-parse --show-toplevel)
TMP_REPO=$(git rev-parse --show-toplevel)/../tmp_repo

mkdir $TMP_REPO
git clone --depth 3 file://$DEEP_REPO $TMP_REPO -b branch_name

# remove the lines below if you want to keep both repositories
cd $TMP_REPO
rm -rf $DEEP_REPO
mkdir $DEEP_REPO
cp -r $TMP_REPO/. $DEEP_REPO
cd $DEEP_REPO
rm -rf $TMP_REPO

如果要保留原始存储库的完整历史记录,请将脚本截断为要克隆的行。然后,具有所需历史记录的存储库副本将存储在$TMP_REPO中。

此外,您可能要编辑浅克隆部分的行: git clone --depth 3 file://$DEEP_REPO $TMP_REPO -b local_backup来满足您的需求。 此外,相应地替换分支名称。在我的用例中,git clone --depth 1 file://$DEEP_REPO $TMP_REPO足以保留最后一次提交。