threads / discuss / 26901

how to squash two commits into only one

Subject: how to squash two commits into only one

## tl;dr

14 messages between Mar 29, 2011 and Mar 30, 2011.

replies: 13people: 8as markdown or json

Lynn Lin· Mar 29, 2011, 05:42 UTC · lore
All,
   I have only have two commits in repo,then I want to squash these
two commit into one through git rebase -i .However it fails

$ git rebase -i HEAD^1 it only show up one commit so can't squash (can't squash without a previous commit)

Any help on this?

Thanks Lynn

Tor Arntsen· Mar 29, 2011, 06:15 UTC · re: Lynn Lin · lore

Re: how to squash two commits into only one

On Tue, Mar 29, 2011 at 07:42, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
Show 7 quoted lines
> All,
>   I have only have two commits in repo,then I want to squash these
> two commit into one through git rebase -i .However it fails
>
> $ git rebase -i HEAD^1
> it only show up one commit so can't squash (can't squash without a
> previous commit)

To squash commits with rebase -i: git log (identify the commit you wish to squash to) git rebase -i <the commit _before_ the one you want to squash to)

e.g. git log 1 2 3 4 .. you want to squash 2 into 3: Use git rebase -i 4 (4 is really a hash of course).

HEAD^some-value is OK sometimes but when I want to fix stuff down in the commit chain somewhere I find it simpler to use the hashes - just mark and paste. Anyway the real point is that with rebase -i you must specify the last commit _before_ the range you want to work with.

-Tor
Lynn Lin· Mar 29, 2011, 08:24 UTC · re: Tor Arntsen · lore

Re: how to squash two commits into only one

On Tue, Mar 29, 2011 at 2:15 PM, Tor Arntsen <tor@spacetec.no> wrote:
Show 29 quoted lines
> On Tue, Mar 29, 2011 at 07:42, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
>> All,
>>   I have only have two commits in repo,then I want to squash these
>> two commit into one through git rebase -i .However it fails
>>
>> $ git rebase -i HEAD^1
>> it only show up one commit so can't squash (can't squash without a
>> previous commit)
>
> To squash commits with rebase -i:
> git log
> (identify the commit you wish to squash to)
> git rebase -i <the commit _before_ the one you want to squash to)
>
> e.g.
> git log
> 1
> 2
> 3
> 4
> ..
> you want to squash 2 into 3: Use git rebase -i 4
> (4 is really a hash of course).
>
> HEAD^some-value is OK sometimes but when I want to fix stuff down in
> the commit chain somewhere I find it simpler to use the hashes - just
> mark and paste.
> Anyway the real point is that with rebase -i you must specify the last
> commit _before_ the range you want to work with.

Thanks .However my case is like: git log 1 2

I want to squash 1 to 2,what's the commit I should specify with rebase -i
> -Tor
>
Tor Arntsen· Mar 29, 2011, 08:50 UTC · re: Lynn Lin · lore

Re: how to squash two commits into only one

On Tue, Mar 29, 2011 at 10:24, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
Show 6 quoted lines
> Thanks .However my case is like:
> git log
> 1
> 2
>
> I want to squash 1 to 2,what's the commit I should specify with rebase -i
That would be 3, i.e. rebase -i 3

That won't work if there are only two commits in total.. rebase needs a commit before the one you want to squash to. But in that case you would do 'git reset HEAD^1' (and end up with only commit 2, and 'M' for the modifications originally done in commit 1), 'git add' <the files changed>, 'git commit --amend', which is exctly what Henrik described earlier.

There is a particular problem if you have this sequence:
git log
 1
 2
 3
 4
 5  (initial commit)

and you want to squash 4 into 5.. there's no hash 6 to rebase -i to. There are several ways to do it, but what I do is something like this: git checkout 4 git checkout -b tmp git reset HEAD^1 <add files> git commit --amend git merge master git branch -M tmp master (<---- rename the tmp branch to 'master')

the new master now has 4 and 5 squashed.

I'm sure others on this list have different ways to do this, but it's the one method that looked obvious to me so that's what I did when I needed it (anyway it's more or less how I fixed historic commits in the past before I learned about 'rebase -i' .. well, rebase -i didn't even exist with the versions of Git I used back then anyway).

-Tor
Alex Riesen· Mar 29, 2011, 09:38 UTC · re: Lynn Lin · lore

Re: how to squash two commits into only one

On Tue, Mar 29, 2011 at 07:42, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
Show 7 quoted lines
> All,
>   I have only have two commits in repo,then I want to squash these
> two commit into one through git rebase -i .However it fails
>
> $ git rebase -i HEAD^1
> it only show up one commit so can't squash (can't squash without a
> previous commit)
$ git rebase -i HEAD~2
8-]
Lynn Lin· Mar 29, 2011, 10:10 UTC · re: Alex Riesen · lore

Re: how to squash two commits into only one

On Tue, Mar 29, 2011 at 5:38 PM, Alex Riesen <raa.lkml@gmail.com> wrote:
Show 11 quoted lines
> On Tue, Mar 29, 2011 at 07:42, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
>> All,
>>   I have only have two commits in repo,then I want to squash these
>> two commit into one through git rebase -i .However it fails
>>
>> $ git rebase -i HEAD^1
>> it only show up one commit so can't squash (can't squash without a
>> previous commit)
>
> $ git rebase -i HEAD~2
>
only have two commits
> 8-]
>
Alex Riesen· Mar 29, 2011, 10:58 UTC · re: Lynn Lin · lore

Re: how to squash two commits into only one

On Tue, Mar 29, 2011 at 12:10, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
Show 13 quoted lines
> On Tue, Mar 29, 2011 at 5:38 PM, Alex Riesen <raa.lkml@gmail.com> wrote:
>> On Tue, Mar 29, 2011 at 07:42, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
>>> All,
>>>   I have only have two commits in repo,then I want to squash these
>>> two commit into one through git rebase -i .However it fails
>>>
>>> $ git rebase -i HEAD^1
>>> it only show up one commit so can't squash (can't squash without a
>>> previous commit)
>>
>> $ git rebase -i HEAD~2
>>
> only have two commits
Uh. That's unusual.
Than yes, "git reset HEAD^; git commit --amend" seems the best solution.
Joshua Juran· Mar 29, 2011, 12:44 UTC · re: Alex Riesen · lore

Re: how to squash two commits into only one

On Mar 29, 2011, at 3:58 AM, Alex Riesen wrote:
Show 22 quoted lines
> On Tue, Mar 29, 2011 at 12:10, Lynn Lin <lynn.xin.lin@gmail.com>  
> wrote:
>> On Tue, Mar 29, 2011 at 5:38 PM, Alex Riesen <raa.lkml@gmail.com>  
>> wrote:
>>> On Tue, Mar 29, 2011 at 07:42, Lynn Lin <lynn.xin.lin@gmail.com>  
>>> wrote:
>>>> All,
>>>>   I have only have two commits in repo,then I want to squash these
>>>> two commit into one through git rebase -i .However it fails
>>>>
>>>> $ git rebase -i HEAD^1
>>>> it only show up one commit so can't squash (can't squash without a
>>>> previous commit)
>>>
>>> $ git rebase -i HEAD~2
>>>
>> only have two commits
>
> Uh. That's unusual.
>
> Than yes, "git reset HEAD^; git commit --amend" seems the best  
> solution.
Actually, that should be:  `git reset --soft HEAD^; git commit --amend`.
Josh
Nguyen Thai Ngoc Duy· Mar 29, 2011, 12:49 UTC · re: Joshua Juran · lore

Re: how to squash two commits into only one

On Tue, Mar 29, 2011 at 7:44 PM, Joshua Juran <jjuran@gmail.com> wrote:
Show 20 quoted lines
> On Mar 29, 2011, at 3:58 AM, Alex Riesen wrote:
>> On Tue, Mar 29, 2011 at 12:10, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
>>> On Tue, Mar 29, 2011 at 5:38 PM, Alex Riesen <raa.lkml@gmail.com> wrote:
>>>> On Tue, Mar 29, 2011 at 07:42, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
>>>>>  I have only have two commits in repo,then I want to squash these
>>>>> two commit into one through git rebase -i .However it fails
>>>>>
>>>>> $ git rebase -i HEAD^1
>>>>> it only show up one commit so can't squash (can't squash without a
>>>>> previous commit)
>>>>
>>>> $ git rebase -i HEAD~2
>>>>
>>> only have two commits
>>
>> Uh. That's unusual.
>>
>> Than yes, "git reset HEAD^; git commit --amend" seems the best solution.
>
> Actually, that should be:  `git reset --soft HEAD^; git commit --amend`.

"git rebase --root" does not seem a bad idea though. I need to amend initial commit a few times and end up using "git reset" without --soft.

-- 
Duy
Joshua Juran· Mar 29, 2011, 13:12 UTC · re: Nguyen Thai Ngoc Duy · lore

Re: how to squash two commits into only one

On Mar 29, 2011, at 5:49 AM, Nguyen Thai Ngoc Duy wrote:
Show 18 quoted lines
> On Tue, Mar 29, 2011 at 7:44 PM, Joshua Juran <jjuran@gmail.com>  
> wrote:
>> On Mar 29, 2011, at 3:58 AM, Alex Riesen wrote:
>>
>>> On Tue, Mar 29, 2011 at 12:10, Lynn Lin <lynn.xin.lin@gmail.com>  
>>> wrote:
>>>
>>>> only have two commits
>>>
>>> Than yes, "git reset HEAD^; git commit --amend" seems the best  
>>> solution.
>>
>> Actually, that should be:  `git reset --soft HEAD^; git commit -- 
>> amend`.
>
> "git rebase --root" does not seem a bad idea though. I need to amend
> initial commit a few times and end up using "git reset" without
> --soft.

Or perhaps have `git commit --amend` issue a warning if doesn't actually amend anything. Sometimes you just want to change the commit message, so you wouldn't want a warning in that case. But other times you're adding changes and updating the commit message at the same time, so you'd want a warning if you forgot to git-add or use --soft. A new --fix option to commit could work like --amend, but fail with an error if no changes are staged. Another option is for --amend to list the staged changes in the edit buffer, or a warning when nothing has changed.

Josh
Will Palmer· Mar 29, 2011, 15:02 UTC · re: Joshua Juran · lore

Re: how to squash two commits into only one

On Tue, 2011-03-29 at 06:12 -0700, Joshua Juran wrote:
Show 23 quoted lines
> On Mar 29, 2011, at 5:49 AM, Nguyen Thai Ngoc Duy wrote:
> 
> > On Tue, Mar 29, 2011 at 7:44 PM, Joshua Juran <jjuran@gmail.com>  
> > wrote:
> >> On Mar 29, 2011, at 3:58 AM, Alex Riesen wrote:
> >>
> >>> On Tue, Mar 29, 2011 at 12:10, Lynn Lin <lynn.xin.lin@gmail.com>  
> >>> wrote:
> >>>
> >>>> only have two commits
> >>>
> >>> Than yes, "git reset HEAD^; git commit --amend" seems the best  
> >>> solution.
> >>
> >> Actually, that should be:  `git reset --soft HEAD^; git commit -- 
> >> amend`.
> >
> > "git rebase --root" does not seem a bad idea though. I need to amend
> > initial commit a few times and end up using "git reset" without
> > --soft.
> 
> Or perhaps have `git commit --amend` issue a warning if doesn't  
> actually amend anything. ............................................

I like this idea. It's been in my notes for a while, but seems like it has a lot of potential to make existing scripts noisy for no reason. I do agree with the change, however.

The only constructive thing I'd add, as it's sitting in my notes right
next to "Warn if "git commit --amend" introduces no changes":
 - Add "git commit --reword", like --amend, but without the above
   warning

This would fit in with the existing names from "git rebase -i". --fixup (for "like --amend but do not ask for a message") seems like a sensible addition to those to, also following the lead of rebase -i, but --fixup=<commit> already means something different (though related), so it is probably a bad idea to overload --fixup with no =<commit>.

Show 16 quoted lines
> ........................ Sometimes you just want to change the commit  
> message, so you wouldn't want a warning in that case.  But other times  
> you're adding changes and updating the commit message at the same  
> time, so you'd want a warning if you forgot to git-add or use --soft.   
> A new --fix option to commit could work like --amend, but fail with an  
> error if no changes are staged.  Another option is for --amend to list  
> the staged changes in the edit buffer, or a warning when nothing has  
> changed.
> 
> Josh
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Junio C Hamano· Mar 29, 2011, 18:28 UTC · re: Nguyen Thai Ngoc Duy · lore

Re: how to squash two commits into only one

Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:
>> Actually, that should be: `git reset --soft HEAD^; git commit --amend`.
>
> "git rebase --root" does not seem a bad idea though.

The lack of this did't annoy me enough (one woudln't have to deal with root commits too often) so I wouldn't bother implementing it myself, but "git rebase --root" especially with "-i" would be a nice addition.

i.e. well written and explained patches welcome.
Dirk Süsserott· Mar 30, 2011, 19:22 UTC · re: Junio C Hamano · lore

Re: how to squash two commits into only one

Am 29.03.2011 20:28 schrieb Junio C Hamano:
Show 11 quoted lines
> Nguyen Thai Ngoc Duy<pclouds@gmail.com>  writes:
>
>>> Actually, that should be: `git reset --soft HEAD^; git commit --amend`.
>>
>> "git rebase --root" does not seem a bad idea though.
>
> The lack of this did't annoy me enough (one woudln't have to deal with
> root commits too often) so I wouldn't bother implementing it myself, but
> "git rebase --root" especially with "-i" would be a nice addition.
>
> i.e. well written and explained patches welcome.

Lynn, this won't help you right now, but perhaps in the future: When I create a new repo, the first thing I do is creating an empty commit, like so:

git init my_repo cd my_repo git commit --allow-empty -m "Initial commit (empty)"

This creates an empty root commit which is helpful not only in your case.

Another way to solve your problem would be to prepend that empty root commit to your repo afterwards. It's a bit weird, but it works -- at least if you don't have branches (except for "master").

git checkout --orphan new_master (1) git rm -rf . (2) git commit --allow-empty -m "Initial commit (empty)" (3) git rebase new_master master (4) git branch -d new_master (5)

(1) creates a new branch 'new_master' which is totally independent
     of any other branch in the repo, thus the option's name. But it
     silently does a "git add .", i.e. it stages all files that were
     checked out before issuing the command. See 'checkout' docs
     for details.
(2) removes all the files staged in (1), so that you have a new
     starting point which is really clean.
(3) creates the empty root commit on 'new_master'
(4) replays all changes of 'master' to 'new_master'. 'new_master'
     then has three commits: the root commit and the two commits from
     'master'
(5) removes the 'new_master' which is no longer needed.

And NOW you can do your 'rebase -i <root_commit>' to squash your actual commits.

If you have more than one branch you would have to repeat step (4) with the other branches.

HTH, Dirk

Lynn Lin· Mar 29, 2011, 06:04 UTC · lore

Re: how to squash two commits into only one

On Tue, Mar 29, 2011 at 1:59 PM, Henrik Hautakoski <henrik@fiktivkod.org> wrote:
> You can do a soft reset and amend the changes to the root commit.
> git reset HEAD^1
> (add the files)
> git commit --amend
really good!

Thanks Lynn

Show 26 quoted lines
> On Tue, Mar 29, 2011 at 07:42, Lynn Lin <lynn.xin.lin@gmail.com> wrote:
>>
>> All,
>>   I have only have two commits in repo,then I want to squash these
>> two commit into one through git rebase -i .However it fails
>>
>> $ git rebase -i HEAD^1
>> it only show up one commit so can't squash (can't squash without a
>> previous commit)
>>
>>
>> Any help on this?
>>
>> Thanks
>> Lynn
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>
> --
> Henrik Hautakoski
> henrik@fiktivkod.org
>

← back to recent threads