Here\'s an example:
>git status
# On branch master
nothing to commit (working directory clean)
>git checkout -b test-branch
>vi test.c
>git add t
Have you tried: git rebase -i master
?
Ok, I'm asuming the branch is called "feature" and it was branched from "master".
There's this little git command called merge-base. It takes two commits and gives you the first common ancestor of both of those. So...
git merge-base feature master
...will give you the first common ancestor of those two commits. Guess what happens when you pass that commit to git rebase -i, like...
git rebase -i `git merge-base feature master`
Interactive rebase from the first common ancestor of both master and feature branch. Profit! ;)
Use gitk (*nix), or gitx (OS X) or similar on other platforms, and have a look at which commit was the root of your branch. Then run:
git rebase -i <the SHA hash of the root commit>
For example, I have a repository that I inspected using gitx:
Now that I know the root hash I can run this:
git rebase -i 38965ed29d89a4136e47b688ca10b522b6bc335f
And my editor pops up with this and I can rearrange/squash/whatever as I please.
pick 50b2cff File 1 changes.
pick 345df08 File 2 changes.
pick 9894931 File 3 changes.
pick 9a62b92 File 4 changes.
pick 640b1f8 File 5 changes.
pick 1c437f7 File 6 changes.
pick b014597 File 7 changes.
pick b1f52bc File 8 changes.
pick 40ae0fc File 9 changes.
# Rebase 38965ed..40ae0fc onto 38965ed
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
I'm sure there's some magic way to convince git to figure out the root of the tree automatically, but I don't know what it is.
EDIT: That magic is this:
git log master..other_feature | cat
Which will show you all the commits on that branch, and piping to cat will disable the pager so you see the first commit immediately.
EDIT: combining the above gives a fully automated solution:
git rebase -i `git log master..other_feature --pretty=format:"%h" | tail -n 1`~
Since Git v1.7.10, you can just run git rebase
without argument, and it will find the fork point and rebase your local changes on the upstream branch.
You need to have configured the upstream branch for this to work (i.e. git pull
without argument should work).
For more details, see the docs for git rebase:
If is not specified, the upstream configured in branch..remote and branch..merge options will be used (see git-config[1] for details) and the --fork-point option is assumed. If you are currently not on any branch or if the current branch does not have a configured upstream, the rebase will abort.
A general solution (if you don't know the name of the upstream branch) is:
git rebase -i @{upstream}
Note that if your upstream (probably a tracking branch) has updated since you last rebased, you will pull in new commits from the upstream. If you don't want to pull in new commits, use
git rebase -i `git merge-base --all HEAD @{upstream}`
but that is a bit of a mouthful.
git rebase -i --onto @{u}... @{u}
Interactive rebase starting from the single merge point of HEAD and its upstream including all commits in HEAD that are not in its upstream.
In other words exactly what you want.