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

如何将所有git提交压缩为一个?,git,rebase,git-rebase,squash,git-rewrite-history,Git,Rebase,Git Rebase,Squash,Git Rewrite History,如何将整个存储库压缩到第一次提交 我可以重新设置第一次提交的基础,但这将使我有2次提交。 有没有一种方法可以在第一次提交之前引用提交?我读了一些关于使用嫁接的文章,但从未对其进行过太多的研究 无论如何,您可以使用以下方法手动挤压最后2次提交: git reset HEAD~1 git add -A git commit --amend 也许最简单的方法就是使用工作副本的当前状态创建一个新的存储库。如果要保留所有提交消息,可以先执行git log>original.log,然后在新存储库中编辑初

如何将整个存储库压缩到第一次提交

我可以重新设置第一次提交的基础,但这将使我有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-rebase--interactive
将所有提交压缩成一个提交。现在你剩下两个任务要完成。要做到这一点,请阅读


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

您不能使用
git branch-D
,因为它有一个安全阀来阻止您删除当前分支

这将使您回到“初始提交”状态,在该状态下,您可以从新的初始提交开始

git update-ref -d refs/heads/master
git commit -m "New initial commit"
这将使用HEAD树创建一个孤立提交,并在stdout上输出其名称(SHA-1)。然后在那里重置你的分支

git reset SHA-1

要在一个步骤中完成上述操作:

git reset $(git commit-tree HEAD^{tree} -m "commit message")
截至,您可以使用git-rebase--root-i

对于除第一次提交以外的每次提交,将
拾取
更改为
挤压

更新 我制作了一个别名
git squash all

示例用法
git squash all“一个全新的开始”

注意:可选消息用于提交消息,如果省略,它将默认为“新开始”

也可以使用以下命令创建别名:

git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f'

一班轮 这里,提交消息“
A new start
”只是一个示例,请随意使用您自己的语言

TL;博士 无需挤压,使用
git commit tree
创建一个孤立提交并执行它

说明
  • 通过git提交树创建单个提交

    git commit tree HEAD^{tree}-m“一个新的开始”
    所做的是:

  • 基于提供的树对象创建新的提交对象 并在标准输出上发出新的提交对象id。日志消息是 从标准输入读取,除非给出-m或-F选项

    表达式
    HEAD^{tree}
    表示与
    HEAD
    对应的树对象,即当前分支的尖端。见和

  • 将当前分支重置为新提交
  • 然后,
    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")
    

    这避免了将模板repo添加为远程(
    源文件
    或其他文件),并将模板repo的历史折叠到初始提交中。

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

    git update-ref -d refs/heads/master
    git commit -m "New initial commit"
    
    git rebase --interactive --root
    
    如果可以工作,那么大量提交(例如,数百次提交)是不切实际的,因为rebase操作可能会非常缓慢地运行以生成交互式rebase编辑器提交列表,以及运行rebase本身

    在压缩大量提交时,这里有两个更快、更高效的解决方案:

    替代解决方案#1:孤立分支 您只需在当前分支的尖端(即最近的提交)创建一个新的孤立分支。这个孤立分支形成了一个全新的、独立的提交历史树的初始根提交,这实际上相当于压缩所有提交:

    git签出——孤立的新主机
    git commit-m“为新的初始提交输入提交消息”
    #用新的主分支引用覆盖旧的主分支引用
    git branch-M新主控
    
    文件:

    替代解决方案#2:软重置 另一个有效的解决方案是简单地对根提交使用混合重置或软重置

    重置之前的git分支 git重置——软 修改最后一次提交 #验证新修改的根目录是否相同 #来自上一个分支状态 重置前吉特差异 文件:


    以下是我如何做到这一点的,以防它对其他人有用:

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

    从记录开始

    git log --oneline
    
    滚动至首次提交,复制SHA

    git reset --soft <#sha#>
    
    确保所有内容都是绿色的,否则运行
    git add-A

    git commit --amend
    
    将所有当前更改修改为当前首次提交


    现在强制推送此分支,它将覆盖其中的内容。

    此答案改进了上面的几个(请投票支持),假设除了创建一个提交(无父项无历史记录),您还希望保留该提交的所有提交数据:

    • 作者(姓名和电子邮件)
    • 作者日期
    • 提交人(姓名和电子邮件)
    • 承诺日期
    • 通信日志消息
    当然,新的/单个提交的提交SHA将改变,因为它代表了一个新的(非)历史,成为一个无父/根提交

    这可以通过读取
    git日志
    并为
    git提交树
    设置一些变量来实现。假设您希望从新分支的
    one commit
    中的
    master
    创建单个commit,并保留commit da
    git log --oneline
    
    git reset --soft <#sha#>
    
    git status
    
    git commit --amend
    
    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 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 reset your-first-commit-hashtag
    git add .
    git commit --amend
    
    git rebase -i HEAD~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
    
    git rebase -X ours -i 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.
    
    git merge origin/master && git reset --soft origin/master
    
    git log -4
    
    <your_third_commit_sha>
    <your_second_commit_sha>
    <your_first_commit_sha>
    <master_branch_commit_sha - your branch created from master>
    
    git reset --soft <master_branch_commit_sha>
    
    git status
    
    git commit -m 'specify details'
    
    git push -f