Squashing normal commits
Using the following repository:we can combine the last two commits (c172641 and 24f5ad2) by rebasing up to the first commit:$ git log --oneline
c172641 Fix second file
24f5ad2 Another file
97c9d7d Add first file
and specify the following commands in the interactive rebase screen:$ git rebase -i 97c9d7d
which will rewrite the history into this:pick 24f5ad2 Another file
squash c172641 Fix second file
$ git log --oneline
1a9d5e4 Another file
97c9d7d Add first file
Rebasing the initial commit
Trying to include the initial commit in the interactive rebase screen will return this error:and squashing the top commit in the interactive rebase screen:$ git rebase -i 97c9d7d^
fatal: Needed a single revision
Invalid base
will return this error:$ git rebase -i 97c9d7d
squash 24f5ad2 Another file
squash c172641 Fix second file
So we need to use a different approach to deal with the initial commit.Cannot 'squash' without a previous commit
Amending the initial commit
Here is an alternative to rebase which will work on commits that don't have a parent.Taking the previously rebased branch:
we can rewind the branch to the initial commit:$ git log --oneline
1a9d5e4 Another file
97c9d7d Add first file
without losing any of the changes introduced in 1a9d5e4 (shown here as uncommitted changes):$ git reset 97c9d7d
$ git log --oneline
97c9d7d Add first file
Then we can reopen commit 97c9d7d and add the changes present in the working directory:$ git status
# On branch master
# Changed but not updated:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: file1
#
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# file2
no changes added to commit (use "git add" and/or "git commit -a")
which will finally give us a fully squashed branch:$ git add .
$ gitc -a --amend -m "Initial version"
$ git log --oneline
fcb85fb Initial version
$ git status
# On branch master
nothing to commit (working directory clean)



3 comments:
this works, but there's a better way. If you use git merge, you can specify the --squash option to tell git to merge everything as one commit.
Of course, that only works if you're merging, not while you're still working on the same branch, like you can with rebase.
git checkout -b thirdbranch firstbranch; git diff firstbranch secondbranch | patch -p1; git add -A; git commit
You could also use the much simpler 'git merge --squash && git commit'
Yes, the mechanism is different: it uses the "merge" machinery, not the "rebase" machinery. But, if it ever makes a difference, you have bigger headaches, and shouldn't be making a "squash commit" in the first place.
Post a Comment