我的 git 存储库包含很多很多(2000+)次提交,例如:
l-- m -- n
/
a -- b -- c -- d -- e -- f -- g -- h -- i -- j -- k
\
x -- y -- z
我想截断旧的日志历史记录 - 从日志历史记录中删除从(例如)提交“f”开始但作为存储库开头的所有提交。
如何做?
为了不丢失一些历史;最好先获取您的存储库的副本:)。我们开始吧:(
<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
以下 2 个命令是可选的 - 它们使您的 git 存储库保持良好状态。
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
git clone
使用--shallow-since
选项为您的问题提供了可能的解决方案。如果自 f
以来只有少量提交,并且计数没有问题,那么您可以使用 --depth
选项。
第二个选项 (
--depth
) 仅克隆指定的分支。如果您需要其他分支,您可以将原始存储库添加为远程并使用 git fetch
并检索它们。
当您对结果感到满意时,删除旧存储库并重命名新存储库以替换它。如果旧存储库是远程的,则在删除后重新创建它并从新存储库推送到其中。
这种方法具有规模和速度的优势。新的存储库仅包含您想要的提交,无需运行
git prune
或 git gc
来删除旧对象(因为它们不存在)。
对于那些使用
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
使用说明:
git-truncate.sh
)。master
)。2c75a32
)并确保该提交没有并行分支!$ ./git-truncate.sh 2c75a32 master
。重要提示:SHA 必须是分支的“一部分”,并且它必须是您要删除的第一个提交。不要传递您想要保留的第一个提交(新的“存储库开头”提交)!
无需变基,来自此链接
git checkout --orphan tmp-master # create a temporary branch
git add -A # Add all files and commit them
git commit -m 'Add files'
git branch -D master # Deletes the master branch
git branch -m master # Rename the current branch to master
git push -f origin master # Force push master branch to Git server
清理仓库:
# Local master tracks origin/master
git branch --set-upstream-to=origin/master master
git gc --aggressive --prune=all # remove the old files
回想一下,Git 提交是一个快照。快照是独立的;它 不需要父母提供任何信息。说到父母,这些 快照链接到零个或多个父级。并且根提交没有 父母。
如果您希望存储库从提交开始
f
那么您可以更改
提交(使用 git-replace(1))有 no 父母。
git replace --graft f
现在
f
(通过其替换引用)将没有父母。 [1]
如果您想让此更改永久存在,那么您需要重写 整个历史从
f
开始。您可以使用第三方工具来完成此操作
git-filter-repo(1)。 [2]
(请注意,以下命令(带有
--force
)应被视为not 是您可以撤消的操作 - 确保它是您想要的。)
git filter-repo --force
--no-replace-objects
作为 git
的参数,以便不使用它们,例如 git --no-replace-objects log