如何将所有git commit压缩为一个?

本文介绍了如何使用git的rebase和reset等命令将一个Git存储库的所有提交压缩成一个单一的提交。通过创建孤立分支、软重置或使用git filter-branch等方法,可以高效地完成这一操作,同时保留原有的提交信息。此外,文中还提供了多种替代解决方案,包括创建新仓库、使用交互式rebase等。
摘要由CSDN通过智能技术生成

您如何压缩整个存储库直到第一次提交?

我可以基于第一次提交,但这会使我留下2次提交。 有没有办法在第一个提交之前引用提交?


#1楼

我读了一些有关使用嫁接的文章,但从未对其进行过多研究。

无论如何,您可以使用以下方法手动压缩最后2次提交:

git reset HEAD~1
git add -A
git commit --amend

#2楼

也许最简单的方法是使用工作副本的当前状态创建一个新的存储库。 如果要保留所有提交消息,则可以先执行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

#3楼

首先,使用git rebase --interactive所有提交压缩为单个提交。 现在,您剩下两次壁球提交了。 为此,请阅读


#4楼

最简单的方法是使用“ plumbing”命令update-ref删除当前分支。

您不能使用git branch -D因为它具有安全阀,可以阻止您删除当前分支。

这将使您回到“初始提交”状态,您可以在其中进行新的初始提交。

git update-ref -d refs/heads/master
git commit -m "New initial commit"

#5楼

echo "message" | git commit-tree HEAD^{tree}

这将创建一个带有HEAD树的孤立提交,并在stdout上输出其名称(SHA-1)。 然后在那儿重置您的分支。

git reset SHA-1

#6楼

更新

我做了一个别名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 ”仅是示例,请随时使用您自己的语言。

TL; DR

无需压榨,使用git commit-tree创建一个孤立的提交并进行处理。

说明

  1. 通过git commit-tree创建一个提交

    git commit-tree HEAD^{tree} -m "A new start"作用是:

    基于提供的树对象创建一个新的提交对象,并在stdout上发出新的提交对象ID。 除非给出-m或-F选项,否则将从标准输入中读取日志消息。

    表达式HEAD^{tree}表示与HEAD对应的树对象,即当前分支的尖端。 请参见Tree-ObjectsCommit-Objects

  2. 将当前分支重置为新提交

    然后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或其他文件),并将模板存储库的历史记录折叠到您的初始提交中。


#7楼

如果您只想将所有提交压缩为根提交,则

git rebase --interactive --root

可以正常工作,对于大量提交(例如,数百次提交)来说,这是不切实际的,因为重新生成基础操作可能会非常缓慢地运行,以生成交互式rebase编辑器提交列表,以及运行重新生成自身。

当您压缩大量提交时,有两个更快,更有效的解决方案:

替代解决方案1:孤立分支

您可以简单地在当前分支的尖端(即最近的提交)创建一个新的孤立分支。 这个孤立的分支构成了一个全新的独立提交历史记录树的初始根提交,这实际上等效于压缩所有提交:

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

文档:

替代解决方案2:软重置

另一个有效的解决方案是简单地对根提交<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

文档:


#8楼

这是我最终要这样做的方式,以防万一它适用于其他人:

请记住,这样做总是有风险的,在开始之前创建保存分支从来都不是坏主意。

从记录开始

git log --oneline

滚动到第一次提交,复制SHA

git reset --soft <#sha#>

替换<#sha#> w /从日志复制的SHA

git status

确保所有内容均为绿色,否则运行git add -A

git commit --amend

将所有当前更改修改为当前第一次提交

现在强行推动此分支,它将覆盖那里的内容。


#9楼

假设除了创建一个提交(无父母无历史记录)之外,您希望保留该提交的所有提交数据,则上述答案在上面的几个方面有所改进(请对它们进行投票):

  • 作者(姓名和电子邮件)
  • 创作日期
  • 提交人(姓名和电子邮件)
  • 提交日期
  • 提交日志消息

当然,新的/单次提交的commit-SHA将发生变化,因为它表示新的(非)历史记录,成为无父母/根提交。

这可以通过阅读git log并为git commit-tree设置一些变量来git commit-tree 。 假设您要在新分支one-commitmaster创建单个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
')

#10楼

用嫁接壁球

添加文件.git/info/grafts ,在其中放置您想要成为根的提交哈希

git log现在将从该提交开始

为了使其“真实”运行git filter-branch


#11楼

我通常这样做:

  • 确保所有内容都已提交,并记下最新的提交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强制推送您的更改


#12楼

创建一个备份

git branch backup

重置为指定的提交

git reset --soft <#root>

然后将所有文件添加到暂存

git add .

提交而不更新消息

git commit --amend --no-edit

推送新的分支并压缩回购

git push -f

#13楼

一行共6个字

git checkout --orphan new_root_branch  &&  git commit

#14楼

在最新版本的git中,可以使用git rebase --root -i

对于除第一次提交之外的每个提交,将pick更改为squash

Git压缩本地仓库的所有文件并传送到远程仓库通常是指将本地的改动打包成一个提交(commit),然后推送到远程仓库。这里的关键操作是"压缩"或"合并"多个提交为一个,以便于更简洁地传输。以下是这一过程的一般步骤: 1. 确保所有本地的更改都已经提交,如果有未提交的更改,需要先使用`git add`添加到暂存区,然后用`git commit`提交。 2. 使用`git rebase`命令的交互模式(`-i`)来合并多个提交。你可以选择将最近的几个提交合并为一个提交,命令格式如下: ``` git rebase -i HEAD~N ``` 这里的`N`代表你想要合并的提交数量,`HEAD~N`表示从当前分支的最新提交开始向前数N个提交。 3. 在打开的文本编辑器中,你会看到最近的N个提交列表。将除了第一个提交外的其他提交前的`pick`改为`squash`或者`fixup`(如果你不想要保留这些提交的提交信息,就使用`fixup`,否则使用`squash`)。保存并关闭编辑器,Git会自动开始合并过程。 4. 如果使用了`squash`,Git会打开另一个编辑器让你合并这些提交的提交信息,根据需要修改后保存退出。 5. 完成这些步骤后,你的本地仓库就会只有一个包含之前所有提交内容的新提交。现在可以使用`git push`命令将这个提交推送到远程仓库了。 ``` git push origin <branch-name> ``` 这里的`<branch-name>`是你当前所在的分支名称。 6. 如果你的本地分支领先远程分支多个提交,并且远程分支设置了保护不允许强制推送,你可能需要使用`git push --force-with-lease`命令来安全地强制推送。 需要注意的是,`git rebase`操作会改写提交历史,这可能会影响到其他协作者。在执行这样的操作之前,最好先与团队成员沟通,确保不会对其他人的工作造成影响。另外,如果你的本地提交已经推送到了远程仓库,那么在改写历史后推送时要格外小心,以避免可能的冲突和数据丢失。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值