下面是git历史记录树,其中突出显示了我要保留的三个提交。我怎样才能让其他一切从字面上消失,好像它们从未存在过一样?
我尝试使用here的答案,但我不断得到以下内容:
fatal: Needed a single revision
Does not point to a valid commit: e147db0477dbb21e74615f4bfff06378b7d269c8^
答案 0 :(得分:2)
三个突出显示的提交中的第一个是合并。如果你保留它,你必须(真的,它不是一个选项)保留你不想要的5个提交。 (浅层克隆可以在深化之前省略它们,但它们在逻辑上仍然存在,即使不是物理存在的。)
因此,你需要做的是做一个新的提交,你可以指向master
和origin/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
足以保留最后一次提交。