Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use interactive rebase on the first (root) commit of a branch?

Tags:

git

rebase

squash

If I'm in the following situation,

$ git log --oneline
* abcdef commit #b
* 123456 commit #a

I know I can always run

$ git reset HEAD~ 
$ git commit --amend

However, I tried to run

$ git rebase -i HEAD~2

but I got

fatal: Needed a single revision
invalid upstream HEAD~2

Hence my question: is there a way to use git rebase to squash these two commits or not?

like image 984
Shubham Chaudhary Avatar asked May 16 '15 14:05

Shubham Chaudhary


People also ask

Can you squash the first commit?

Using the --root option with the rebase command, we were able to squash the first two commits into a single one.

How do I use git interactive rebase?

You can run rebase interactively by adding the -i option to git rebase . You must indicate how far back you want to rewrite commits by telling the command which commit to rebase onto. Remember again that this is a rebasing command — every commit in the range HEAD~3..

How do I change the first commit message?

The easiest way to amend a Git commit message is to use the “git rebase” command with the “-i” option and the SHA of the commit before the one to be amended.


2 Answers

You want to rebase to the root commit of your master branch. More specifically, to squash the two commits, you need to run

git rebase -i --root

and then substitute squash for pick on the second line in the buffer of the editor that pops up:

pick 123456 a                                                        
squash abcdef b

I refer you to the git-rebase man page for more details about that flag:

--root

Rebase all commits reachable from <branch>, instead of limiting them with an <upstream>. This allows you to rebase the root commit(s) on a branch. [...]

Example of an interactive rebase of the root

# Set things up
$ mkdir testgit
$ cd testgit
$ git init

# Make two commits
$ touch README
$ git add README
$ git commit -m "add README"
$ printf "foo\n" > README
$ git commit -am "write 'foo' in README"

# Inspect the log
$ git log --oneline --decorate --graph
* 815b6ca (HEAD -> master) write 'foo' in README
* 630ede6 add README

# Rebase (interactively) the root of the current branch: 
# - Substitute 'squash' for 'pick' on the second line; save and quit the editor.
# - Then write the commit message of the resulting commit; save and quit the editor.
$ git rebase -i --root
[detached HEAD c9003cd] add README; write 'foo' in README
 Date: Sat May 16 17:38:43 2015 +0100
 1 file changed, 1 insertion(+)
 create mode 100644 README
Successfully rebased and updated refs/heads/master.

# Inspect the log again
$ git log --oneline --decorate --graph
* c9003cd (HEAD -> master) add README; write 'foo' in README
like image 88
jub0bs Avatar answered Sep 24 '22 17:09

jub0bs


It seems this parameter may help:

--root 

Rebase all commits reachable from <branch>, instead of limiting them with an <upstream>. This allows you to rebase the root commit(s) on a branch.

This should let you squash (I guess you actually want to fixup) your second commit onto the first:

git rebase --root -i

Take care in understanding what the --root option does, because in your case it answers your needs, but may be tricky for instance when used in branches, because it will rebase onto the farthest ancestor in the history that is reachable (ie. the root of the tree); so rebase --root will rebase z on a thru A-B-D-E-X-Y-Z:

master      A-B-C
               \
upstream        D-E  
                   \     
current branch      X-Y-Z
like image 12
guido Avatar answered Sep 23 '22 17:09

guido