这个问题已经有一个答案在这里:

git rebase --interactive <commit> 你可以壁球任何数量的承诺一起纳入一个单一的。

这是所有伟大的除非你想打壁球承诺进入初始提交。这似乎不可能做到的。

是否有任何方法来实现它吗?


适度相关:

在一个相关的问题,我设法拿出一个不同的方法来需要的胚对第一承诺,这是,嗯,使它的第二个。

如果你有兴趣: 文件怎么插入一个提交第一、转移所有其他人吗?

有帮助吗?

解决方案

更新月2012(git1.7.12+)

你现在可以重订,所有提交的最根本和选择第二个承诺 Y 被压扁的第一个 X.

git rebase -i --root master

pick sha1 X
squash sha1 Y
pick sha1 Z
git rebase [-i] --root $tip

这个命令现在可以用于所有改写历史上领先从"$tip"下的根本承诺。

看看 提交df5df20c1308f936ea542c86df1e9c6974168472上。克里斯*韦伯(arachsys).


原来的答复(2009年)

我相信你会发现不同的食谱,在这样的问题"我如何相结合的第一次两次提交的个混库?"

查尔斯*贝利 提供有最大的 详细的回答, ,提醒我们这一承诺是一个完整的树(不仅仅是比较从前一个国)。
和这里的老commit("初始提交")和新的承诺(结果的挤压)将没有任何共同的祖先。
这意味着你不能"commit --amend"初始提交入新的一个,然后衍合到新的初始提交的历史,以前的初始承诺(许多冲突)

(最后一句是不再真实的 git rebase -i --root <aBranch>)

而不是(与 A 原来的"初始承诺", B 随后提交需要压扁成最初的一个):

  1. 回到最后提交的,我们希望的形式的初始提交(分离头):

    git checkout <sha1_for_B>
    
  2. 重置分支指针向初始提交,但留下的指数和工作树不变:

    git reset --soft <sha1_for_A>
    
  3. 修改初始树木用树'B':

    git commit --amend
    
  4. 临时标记这一新的初始提交(或者你可以记住新的承诺sha1手动):

    git tag tmp
    
  5. 回到原来的分支(假定掌握这个例):

    git checkout master
    
  6. 重放所有提交后的B到新的初始提交:

    git rebase --onto tmp <sha1_for_B>
    
  7. 删除临时标记:

    git tag -d tmp
    

这种方式,"rebase --onto"不引入冲突期间合并,因为它rebases历史 最后一次提交(B)被压扁成最初的一个(这是 A)来 tmp (代表的被压扁的新初次提交):琐碎快进合并只。

那工作对"A-B",但也"A-...-...-...-B"(任何数量的承诺可以被压扁的成最初的一个这种方式)

其他提示

我已经重新设计VonC的脚做的一切自动和不要问我任何东西。你给这两个提交SHA1s,它将壁球之间的一切成一个他们提交的名为"被压扁的历史":

#!/bin/sh
# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout $2

# reset the branch pointer to the initial commit (= $1),
# but leaving the index and working tree intact.
git reset --soft $1

# amend the initial tree using the tree from $2
git commit --amend -m "squashed history"

# remember the new commit sha1
TARGET=`git rev-list HEAD --max-count=1`

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after $2 onto the new initial commit
git rebase --onto $TARGET $2

为什么它的价值,避免这个问题总是创建一个"禁运"的第一承诺,其唯一的在该仓库是空的。gitignore:

https://github.com/DarwinAwardWinner/git-custom-commands/blob/master/bin/git-myinit

这样,从未有任何理由的混乱与第一提交。

如果你只是想压制所有提交到一个单一、初始提交的,只是重置库和修订第一个承诺:

git reset hash-of-first-commit
git add -A
git commit --amend

Git重置将离开的工作树完整,所以一切都是仍然存在。所以就增加该文件令添加命令,而修订的第一个提交这些变化。相比变基-我你会失去能力合并从初意见。

这将壁球第二提交到的第一个:

A-B-C-... -> AB-C-...

git filter-branch --commit-filter '
    if [ "$GIT_COMMIT" = <sha1ofA> ];
    then
        skip_commit "$@";
    else
        git commit-tree "$@";
    fi
' HEAD

提交信息AB将从B(虽然我喜欢从一)。

具有同样的效果如Uwe克莱-柯尼希的答案,但适用于非最初的一个。

挤压的第一和第二承诺将导致在第一个承诺正在改写。如果你有多于一个分支,这是基于第一承诺,你要剪掉那的分支。

考虑下面的例子:

a---b---HEAD
 \
  \
   '---d

挤压a和b入一个新的提交"ab"将导致在两个不同的树木,在大多数情况下是不可取的,因为 混帐合并混帐变基 将不再工作跨越两个分支机构。

ab---HEAD

a---d

如果你真的想要这个,这是可以做到的。看看 混帐过滤器的分支 对于一个强大的(危险)的工具,为历史重写。

你可以偏滤分支。例如

git filter-branch --parent-filter \
'if test $GIT_COMMIT != <sha1ofB>; then cat; fi'

这种结果在a-b-C扔掉的提交日志的A.

你可以使用的变基互动式的修改的最后两个提交之前,他们已经被推到一个遥

git rebase HEAD^^ -i

有一个简单的方法来做到这一点。让我们假设你是对的 master

创建一个新的孤立分支,这将删除所有提交的历史:

$ git checkout --orphan new_branch

添加初始提交信息:

$ git commit -a

摆脱旧未并入的主分支机构:

$ git branch -D master

重新命名你的当前分支 new_branchmaster:

$ git branch -m master
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top