您如何将整个存储库压缩到第一次提交?
我可以重新提交到第一次提交,但这会给我留下 2 次提交。有没有办法在第一个提交之前引用提交?
您如何将整个存储库压缩到第一次提交?
我可以重新提交到第一次提交,但这会给我留下 2 次提交。有没有办法在第一个提交之前引用提交?
从git 1.6.2开始,您可以使用git rebase --root -i
.
对于除第一次以外的每个提交,更改pick
为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"
注意:可选消息用于提交消息,如果省略,它将默认为“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"
是:
根据提供的树对象创建一个新的提交对象,并在标准输出上发出新的提交对象 ID。除非给出 -m 或 -F 选项,否则从标准输入读取日志消息。
表达式HEAD^{tree}
表示对应的树对象HEAD
,即当前分支的尖端。请参阅树对象和提交对象。
然后git reset
只需将当前分支重置为新创建的提交对象。
这样,工作区中的任何内容都不会被触及,也不需要 rebase/squash,这使得它非常快。所需时间与存储库大小或历史深度无关。
这对于使用另一个存储库作为模板/原型/种子/骨架在新项目中创建“初始提交”很有用。例如:
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 操作可能会运行非常缓慢以生成交互式 rebase 编辑器提交列表,以及运行 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
文档:
另一个有效的解决方案是简单地对根提交使用混合或软重置<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 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
echo "message" | git commit-tree HEAD^{tree}
这将使用 HEAD 树创建一个孤立的提交,并在标准输出上输出其名称 (SHA-1)。然后在那里重置你的分支。
git reset SHA-1
一步完成上述操作:
git reset $(git commit-tree HEAD^{tree} -m "Initial commit.")
这是我最终这样做的方式,以防万一它适用于其他人:
请记住,做这样的事情总是有风险的,在开始之前创建一个保存分支从来都不是一个坏主意。
从记录开始
git log --oneline
滚动到第一个提交,复制 SHA
git reset --soft <#sha#>
<#sha#>
用从日志中复制的 SHA替换
git status
确保一切都是绿色的,否则运行git add -A
git commit --amend
将所有当前更改修改为当前第一次提交
现在强制推送这个分支,它将覆盖那里的内容。
我读过一些关于使用移植物的文章,但从未对其进行过深入研究。
无论如何,您可以使用以下方式手动压缩最后 2 次提交:
git reset HEAD~1
git add -A
git commit --amend
最简单的方法是使用“管道”命令update-ref
删除当前分支。
您不能使用git branch -D
它,因为它有一个安全阀来阻止您删除当前分支。
这使您回到“初始提交”状态,您可以从新的初始提交开始。
git update-ref -d refs/heads/master
git commit -m "New initial commit"
一行6个字:
git checkout --orphan new_root_branch && git commit
首先,使用 . 将所有提交压缩为一个提交git rebase --interactive
。现在你剩下两个提交到壁球。为此,请阅读任何
创建备份
git branch backup
重置为指定的提交
git reset --soft <#root>
然后将所有文件添加到暂存
git add .
提交而不更新消息
git commit --amend --no-edit
将带有压缩提交的新分支推送到 repo
git push -f
为此,您可以将本地 git 存储库重置为第一个提交主题标签,这样您在该提交之后的所有更改都将被取消,然后您可以使用 --amend 选项提交。
git reset your-first-commit-hashtag
git add .
git commit --amend
然后根据需要编辑第一个提交名称并保存文件。
添加一个文件.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
以强制推送您的更改
假设您的分支中有 3 个提交,并且它已经被推送到远程分支。
例子:
git log -4
将显示如下结果:
<your_third_commit_sha>
<your_second_commit_sha>
<your_first_commit_sha>
<master_branch_commit_sha - your branch created from master>
您想将最后 3 个提交压缩为一个提交并推送到远程分支。以下是步骤。
git reset --soft <master_branch_commit_sha>
现在所有提交更改都已集成但未提交。通过以下方式验证:
git status
使用消息提交所有更改:
git commit -m 'specify details'
强制将单个提交推送到远程分支:
git push -f
对我来说,它是这样工作的:我总共有 4 次提交,并使用了交互式变基:
git rebase -i HEAD~3
第一个提交仍然存在,我进行了 3 个最新提交。
如果您卡在接下来出现的编辑器中,您会看到如下内容:
pick fda59df commit 1
pick x536897 commit 2
pick c01a668 commit 3
您必须首先提交并将其他人压扁。你应该拥有的是:
pick fda59df commit 1
squash x536897 commit 2
squash c01a668 commit 3
为此,使用 INSERT 键更改“插入”和“编辑”模式。
要保存并退出编辑器,请使用:wq
. 如果您的光标位于这些提交行之间或其他地方,请按 ESC 并重试。
结果我有两个提交:第一个仍然存在,第二个带有消息“这是 3 个提交的组合。”。
在此处查看详细信息: https ://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit
这对我来说效果最好。
git rebase -X ours -i master
这将使 git 更喜欢您的功能分支来掌握;避免繁重的合并编辑。您的分支需要与 master 保持同步。
ours
This resolves any number of heads, but the resulting tree of the merge is always that of the current
branch head, effectively ignoring all changes from all other branches. It is meant to be used to
supersede old development history of side branches. Note that this is different from the -Xours
option to the recursive merge strategy.
这个答案改进了上面的几个(请投票),假设除了创建一个提交(no-parents no-history)之外,您还希望保留该提交的所有提交数据:
当然,新/单一提交的提交 SHA 会改变,因为它代表一个新的(非)历史,成为无父/根提交。
这可以通过读取git log
和设置一些变量来完成git commit-tree
。假设你想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} <<COMMITMESSAGE
$COMMIT_MESSAGE
COMMITMESSAGE
')
由于我在这里提出的解决方案遇到了一些问题,我想分享一个非常简单的解决方案(将功能分支上的所有提交压缩为一个):
git merge origin/master && git reset --soft origin/master
前面的 merge cmd 确保在提交时不会影响您最近从 master 所做的更改!之后,只需提交更改并执行git push -f
当我从 git 存储库恢复模板时,我通常会压缩整个树,以获得更清晰的历史记录并确保符合法律规定。我的工作流程如下所示:
git clone https://git.invalid/my-awesome-template.git my-awesome-foo
cd !$
git branch -M master my-awesome-template/master
git checkout --orphan master
git rm -rf /
git commit --allow-empty --allow-empty-message -m 'Initial commit'
git merge --squash --allow-unrelated-histories my-awesome-template/master
git commit
git branch -D my-awesome-template/master
# you can now `drop' that "Initial commit":
git rebase -i --root
这会将您的整个历史记录压缩成一条大的提交消息。
在这个特定的例子中:
master
是工作分支my-awesome-template/master
是一个中间分支