How to squash all git commits into one?
如何将整个存储库压缩到第一次提交?
我可以重设为第一个提交,但这将留给我两个提交。在第一个提交之前是否有引用提交的方法?
在Git的最新版本中,您可以使用
对于除第一个外的每个提交,将
更新
我化名为
示例用法:
1 2 | [alias] squash-all ="!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f" |
。
警告:请记住提供注释,否则将使用默认的提交消息"新的开始"。
也可以使用以下命令创建别名:
1 | git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m"${1:-A new start}");};f' |
一个衬垫
1 | git reset $(git commit-tree HEAD^{tree} -m"A new start") |
。
注:这里"
不需要挤压,使用
通过
Creates a new commit object based on the provided tree object
and emits the new commit object id on stdout. The log message is
read from the standard input, unless -m or -F options are given.
号
表达式
将当前分支重置为新提交
然后,
这样,工作区中的任何东西都不会被触摸,也不会需要重新平衡/挤压,这使得它非常快。所需的时间与存储库的大小或历史深度无关。
变更:项目模板的新回购这对于使用另一个存储库作为模板/原型/种子/骨架在新项目中创建"初始提交"很有用。例如:
1 2 3 4 | 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") |
这样可以避免将模板repo添加为远程(
如果您只想将所有提交压缩到根提交,那么,
1 | git rebase --interactive --root |
。
可以工作,对于大量提交(例如,数百次提交)来说是不切实际的,因为REBASE操作可能会非常缓慢地运行以生成交互式的REBASE编辑器提交列表,以及运行REBASE本身。
当您压缩大量提交时,以下是两个更快、更高效的解决方案:
备选方案1:孤立分支您只需在当前分支的提示(即最新提交)处创建一个新的孤立分支。这个孤立分支形成了一个全新的独立提交历史树的初始根提交,这实际上相当于压扁所有提交:
1 2 3 4 5 | 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结账(1)手册页。
备选方案2:软重置
另一个有效的解决方案是简单地对根提交
1 2 3 4 5 6 7 8 | 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重置(1)手册页。
也许最简单的方法就是用工作副本的当前状态创建一个新的存储库。如果要保留所有提交消息,可以先执行
1 2 3 4 | rm -rf .git git init git add . git commit |
号
或
1 2 3 4 5 6 | git log > original.log # edit original.log as desired rm -rf .git git init git add . git commit -F original.log |
1 | echo"message" | git commit-tree HEAD^{tree} |
这将使用head树创建一个孤立的提交,并在stdout上输出它的名称(sha-1)。然后重新设置你的分支。
1 | git reset SHA-1 |
。
我就是这样做的,以防它对其他人有用:
记住这样做总是有风险的,在开始之前创建一个save分支绝对不是一个坏主意。
从日志开始
1 | git log --oneline |
滚动到第一次提交,复制sha
1 | git reset --soft <#sha#> |
号
将从日志复制的sha替换为
1 | git status |
确保一切都是绿色的,否则运行
1 | git commit --amend |
。
将所有当前更改修改为当前首次提交
现在强制推这个分支,它将覆盖那里的内容。
最简单的方法是使用"管道"命令
您不能使用
这将使您回到"初始提交"状态,在该状态下,您可以从新的初始提交开始。
1 2 | git update-ref -d refs/heads/master git commit -m"New initial commit" |
。
我读过一些关于使用移植物的文章,但从来没有做过太多的调查。
无论如何,您可以手动挤压最后2个提交,如下所示:
1 2 3 | git reset HEAD~1 git add -A git commit --amend |
首先,使用
- 如何组合Git存储库的前两个提交?
- 吉特:如何压扁前两个承诺?
一行6个字
1 | git checkout --orphan new_root_branch && git commit |
。
用嫁接物压扁
添加一个文件
使之"真实"运行
创建备份
1 | git branch backup |
。
重置为指定的提交
1 | git reset --soft <#root> |
。
然后将所有文件添加到临时
1 | git add . |
提交而不更新消息
1 | git commit --amend --no-edit |
。
以压缩的回购承诺推动新的分支机构
1 | git push -f |
这个答案在上面的几项上有所改进(请投票给他们),假设除了创建一个提交(没有父母没有历史记录),您还希望保留该提交的所有提交数据:
- 作者(姓名和电子邮件)
- 作者日期
- 专员(姓名和电子邮件)
- 承诺日期
- 通信日志消息
当然,新的/单个提交的提交sha将改变,因为它代表一个新的(非)历史,成为无父/根提交。
这可以通过读取
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 ') |
我通常这样做:
确保所有内容都已提交,并在出现问题时写下最新的提交ID,或者创建一个单独的分支作为备份
运行
git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD` 将您的头重置为第一次提交,但保持索引不变。自第一次提交以来的所有更改现在都已准备好提交。运行
git commit --amend -m"initial commit" 修改提交到第一个提交并更改提交消息,或者如果要保留现有的提交消息,可以运行git commit --amend --no-edit 。运行
git push -f 以强制推行更改