Beware: git rebase origin master
means git checkout master; git rebase origin
(and then return to the original branch). That's why your reflog shows:
HEAD@{1}: rebase: checkout master
(and then HEAD@{0}: rebase finished: returning to refs/heads/komoto/crop_image
: obviously you were on komoto/crop_image
when you started).
What you did actually run
When you write origin
by itself in this positional argument, your Git follows the six-step process outlined in the gitrevisions documentation. Step 6 reads:
- otherwise, refs/remotes/<refname>/HEAD if it exists.
So if git rev-parse origin/HEAD
succeeds (and the five preceding steps fail), the sequence of commands:
git checkout master
git rebase origin
is equivalent to the sequence:
git checkout master
git rebase origin/master
If there are no commits on your master
that are not already reachable from origin/master
, this does nothing. For a good introduction to reachability, see Think Like (a) Git.
What you should have run
I have a old branch foo
, and wanna make it up to the latest master
.
In general, I prefer to do this as:
git checkout foo
git rebase master
but you can—because of the shortcut that I think people should avoid (it has bad failure modes in older versions of Git)—run:
git rebase master foo
Remember that rebase works by copying commits, so this will first enumerate all non-merge commits reachable from foo
that are not reachable from master
, in a topologically-sorted order,1 saving their hash IDs somewhere.2 It will then use the equivalent of git cherry-pick
3 to copy each such commit, with the copy landing after the previously-copied commit. The first-copied commit lands right after the tip of master
:
...--A--B--C--...--N--O <-- master
\
G--H--I <-- foo
becomes:
G'-H'-I' <-- foo
/
...--A--B--C--...--N--O <-- master
\
G--H--I [abandoned, but still findable as foo@{1}]
where G'-H'-I'
is the sequence of cherry-picked, i.e., copied, commits that correspond to the original commits G-H-I
.
1For a simple chain of commits with no branching and merging, the only correct topological sort is: in order from first to last. If there are branch-and-merge sequences in the chain of commits you are rebasing, rebase picks some valid topological sort, linearizing the commits in the process and omitting merge commits. This is actually sometimes a good idea and what you want, but more often, it's not. Git is growing a new kind of rebase that will be able to handle this better; currently there is an option called --preserve-merges
that attempts to do the job, but is not really adequate and should be avoided except in emergencies.
2This somewhere is literally in the file full of pick
directives when you use git rebase -i
. Each pick hash
directive tells Git to do a cherry-pick of that particular commit, listing its true name: its hash ID. for some other kinds of rebases, the IDs are not as easily visible—but they are still saved somewhere, with the ability to stop the copying process when a copy step fails, then resume from the point where it stopped after you have manually fixed things up.
3An interactive rebase, or a rebase run with -m
or -s
flags, literally uses git cherry-pick
. All rebases probably should default to this, but currently, non-interactive rebases that do not use -m
or -s
use an older method that combines git format-patch
with git am --3way
. See also What is the difference between git cherry-pick and git format-patch | git am?