您如何压缩整个存储库直到第一次提交?
我可以基于第一次提交,但这会使我留下2次提交。 有没有办法在第一个提交之前引用提交?
我读了一些有关使用嫁接的文章,但从未对其进行过多研究。
无论如何,您可以使用以下方法手动压缩最后2次提交:
git reset HEAD~1
git add -A
git commit --amend
也许最简单的方法是使用工作副本的当前状态创建一个新的存储库。 如果要保留所有提交消息,则可以先执行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 rebase --interactive
所有提交压缩为单个提交。 现在,您剩下两次壁球提交了。 为此,请阅读
最简单的方法是使用“ plumbing”命令update-ref
删除当前分支。
您不能使用git branch -D
因为它具有安全阀,可以阻止您删除当前分支。
这将使您回到“初始提交”状态,您可以在其中进行新的初始提交。
git update-ref -d refs/heads/master
git commit -m "New initial commit"
echo "message" | git commit-tree HEAD^{tree}
这将创建一个带有HEAD树的孤立提交,并在stdout上输出其名称(SHA-1)。 然后在那儿重置您的分支。
git reset SHA-1
我做了一个别名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"
警告 :请记住要提供注释,否则将使用默认的提交消息“ A new start”。
或者,您可以使用以下命令创建别名:
git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f'
git reset $(git commit-tree HEAD^{tree} -m "A new start")
注意 :这里的“ A new start
”仅是示例,请随时使用您自己的语言。
无需压榨,使用git commit-tree
创建一个孤立的提交并进行处理。
通过git commit-tree
创建一个提交
git commit-tree HEAD^{tree} -m "A new start"
作用是:
基于提供的树对象创建一个新的提交对象,并在stdout上发出新的提交对象ID。 除非给出-m或-F选项,否则将从标准输入中读取日志消息。
表达式HEAD^{tree}
表示与HEAD
对应的树对象,即当前分支的尖端。 请参见Tree-Objects和Commit-Objects 。
将当前分支重置为新提交
然后git reset
只需将当前分支重置为新创建的提交对象。
这样,工作空间中的任何东西都不会受到影响,也不需要重新设置基准/压扁,这使得处理速度非常快。 而且所需的时间与存储库大小或历史记录深度无关。
这对于在使用另一个存储库作为模板/原型/种子/骨骼的新项目中创建“初始提交”很有用。 例如:
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
可以正常工作,对于大量提交(例如,数百次提交)来说,这是不切实际的,因为重新生成基础操作可能会非常缓慢地运行,以生成交互式rebase编辑器提交列表,以及运行重新生成自身。
当您压缩大量提交时,有两个更快,更有效的解决方案:
您可以简单地在当前分支的尖端(即最近的提交)创建一个新的孤立分支。 这个孤立的分支构成了一个全新的独立提交历史记录树的初始根提交,这实际上等效于压缩所有提交:
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 branch beforeReset
git reset --soft
git commit --amend
# Verify that the new amended root is no different
# from the previous branch state
git diff beforeReset
文档:
这是我最终要这样做的方式,以防万一它适用于其他人:
请记住,这样做总是有风险的,在开始之前创建保存分支从来都不是坏主意。
从记录开始
git log --oneline
滚动到第一次提交,复制SHA
git reset --soft <#sha#>
替换<#sha#>
w /从日志复制的SHA
git status
确保所有内容均为绿色,否则运行git add -A
git commit --amend
将所有当前更改修改为当前第一次提交
现在强行推动此分支,它将覆盖那里的内容。
假设除了创建一个提交(无父母无历史记录)之外,您还希望保留该提交的所有提交数据,则上述答案在上面的几个方面有所改进(请对它们进行投票):
当然,新的/单次提交的commit-SHA将发生变化,因为它表示新的(非)历史记录,成为无父母/根提交。
这可以通过阅读git log
并为git commit-tree
设置一些变量来git commit-tree
。 假设您要在新分支one-commit
从master
创建单个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} <
添加文件.git/info/grafts
,在其中放置您想要成为根的提交哈希
git log
现在将从该提交开始
为了使其“真实”运行git filter-branch
我通常这样做:
确保所有内容都已提交,并记下最新的提交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
强制推送您的更改
创建一个备份
git branch backup
重置为指定的提交
git reset --soft <#root>
然后将所有文件添加到暂存
git add .
提交而不更新消息
git commit --amend --no-edit
推送新的分支并压缩回购
git push -f
git checkout --orphan new_root_branch && git commit
在最新版本的git中,可以使用git rebase --root -i
。
对于除第一次提交之外的每个提交,将pick
更改为squash
。