如何压缩所有的git提交到一个?
你如何压缩你的整个存储库到第一次提交?
我可以重新进行第一次提交,但这会使我有2次提交。 有没有办法在第一个之前引用提交?
也许最简单的方法就是创build一个工作副本当前状态的新的存储库。 如果你想保留所有的提交信息,你可以先做git log > original.log
,然后在新的仓库中编辑你的初始提交信息:
rm -rf .git git init git add . git commit
要么
git log > original.log # edit original.log as desired rm -rf .git git init git add . git commit -F original.log
在最近的git版本中,你可以使用git rebase --root -i
。
对于除第一个之外的每个提交,都要改变为squash
。
更新
我做了一个别名git squash-all
。
用法示例 : git squash-all "a brand new start"
。
[alias] squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m \"${1:-A new start}\");};f"
注意 :记得提供注释,否则将使用默认提交消息“新开始”。
或者您可以使用以下命令创build别名:
git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f'
一个class轮
git reset $(git commit-tree HEAD^{tree} -m "A new start")
注意 :这里“ A new start
”只是一个例子,随意使用你自己的语言。
TL; DR
不需要压缩,使用git commit-tree
来创build一个孤立的提交,并与它一起去。
说明
-
通过
git commit-tree
创build一个单独的提交什么
git commit-tree HEAD^{tree} -m "A new start"
是:基于提供的树对象创build一个新的提交对象,并在stdout上发出新的提交对象ID。 日志消息是从标准input读取的,除非给出-m或-F选项。
expression式
HEAD^{tree}
表示与HEAD
对应的树对象,即当前分支的顶端。 请参阅树对象和提交对象 。 -
重置当前分支到新的提交
然后
git reset
只需重置当前分支到新创build的提交对象。
这样,工作空间中的任何东西都不会被触动,也不需要变形/压扁,这使得它非常快速。 而所需的时间与资源库大小或历史深度无关。
变化:来自项目模板的新回购
这对于在使用另一个存储库作为模板/ archetype / seed / skeleton的新项目中创build“初始提交”很有用。 例如:
cd my-new-project git init git fetch --depth=1 -n https://github.com/toolbear/panda.git git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "initial commit")
这避免了添加模板回购作为一个远程( origin
或其他)和折叠模板回购的历史到您的初始提交。
如果你只想把所有的提交压缩到根提交,然后
git rebase --interactive --root
可以工作,对于大量提交(例如,数百次提交)是不切实际的,因为重新分配操作可能运行得非常慢,以生成交互式重新分配编辑器提交列表,以及自行运行重新分配。
当你压扁大量的提交时,这里有两个更快更有效的解决scheme:
替代解决scheme#1:孤立分行
您可以简单地在当前分支的提示(即最近的提交)中创build一个新的孤立分支。 这个孤立分支形成一个全新的独立的提交历史logging树的初始根提交,这实际上相当于压扁所有的提交:
git checkout --orphan new-master master git commit -m "Enter commit message for your new initial commit" # Overwrite the old master branch reference with the new one git branch -M new-master master
文档:
- git-checkout(1)手册页 。
替代解决scheme#2:软复位
另一个有效的解决scheme是简单地对根提交使用混合或软重置<root>
:
git branch beforeReset git reset --soft <root> git commit --amend # Verify that the new amended root is no different # from the previous branch state git diff beforeReset
文档:
- git-reset(1)手册页 。
echo "message" | git commit-tree HEAD^{tree}
这将使用HEAD树创build一个孤立的提交,并在stdout上输出它的名字(SHA-1)。 然后在那里重新设置你的分支。
git reset SHA-1
最简单的方法是使用“pipe道”命令update-ref
删除当前分支。
你不能使用git branch -D
因为它有一个安全阀来阻止你删除当前分支。
这会让您回到“初始提交”状态,您可以从新的初始提交开始。
git update-ref -d refs/heads/master git commit -m "New initial commit"
以下是我如何做到这一点,以防万一它为别人工作:
请记住,做这样的事情总是有风险的,在开始之前创build一个保存分支是一个不错的主意。
从logging开始
git log --oneline
滚动到第一个提交,复制SHA
git reset --soft <#sha#>
将<#sha#>
replace为从日志中复制的SHA
git status
确保一切都是绿色的,否则运行git add -A
git commit --amend
修改当前首次提交的所有当前更改
现在强行推这个分支,它会覆盖那里的东西。
首先,使用git rebase --interactive
所有提交压缩到一个提交中。 现在你剩下两个提交壁球了。 要做到这一点,阅读任何
- 我如何结合Git仓库的前两个提交?
- git:如何挤压前两个提交?
我读了一些关于使用移植,但从来没有调查过多。
无论如何,你可以像这样手动压缩最后2次提交:
git reset HEAD~1 git add -A git commit --amend
假设除了创build一个提交(no-parents no-history)之外, 还需要保留提交的所有提交数据:
- 作者(姓名和电子邮件)
- 创作date
- 提交者(姓名和电子邮件)
- 承诺date
- 交付日志消息
当然,new / single commit的commit-SHA将会改变,因为它代表一个新的(非)历史,成为一个无父/ root提交。
这可以通过阅读git log
和设置一些variables为git commit-tree
。 假设你想在一个新的分支one-commit
提交中从master
创build一个单一one-commit
,保留上面的提交数据:
git checkout -b one-commit master ## create new branch to reset git reset --hard \ $(eval "$(git log master -n1 --format='\ COMMIT_MESSAGE="%B" \ GIT_AUTHOR_NAME="%an" \ GIT_AUTHOR_EMAIL="%ae" \ GIT_AUTHOR_DATE="%ad" \ GIT_COMMITTER_NAME="%cn" \ GIT_COMMITTER_EMAIL="%ce" \ GIT_COMMITTER_DATE="%cd"')" 'git commit-tree master^{tree} <<COMMITMESSAGE $COMMIT_MESSAGE COMMITMESSAGE ')
用移植物挤压
添加一个文件.git/info/grafts
,在那里放置你想成为你的根的提交散列
git log
现在将从该提交开始
为了让它“真正”运行git filter-branch