Reputation: 11030
I've run into a few merge conflicts with git rebase.
My question is, if I fix the conflicts, do I then do something like this:
git add files
git commit "fixed merge conflicts"
then continue with
git rebase --continue
My other question is if I mess up, can I do
git rebase --abort
and will that remove all the commits?
Upvotes: 0
Views: 68
Reputation: 488453
Based on your comment on jready's answer, your real question is whether you should save your original chain of commits somewhere / somehow.
Rebase, at a sort of fundamental level, works by copying (because commits can never be changed—this includes their backwards-looking links). Branch names simply point to some specific commit. If we draw the commits as nodes in a graph, what we have looks like this:
...--F--G--H--I <-- origin/whatever
\
J--K--L <-- your-branch
If you run git checkout your-branch && git rebase origin/whatever
, Git must copy commit J
, by turning it into a set of changes vs its parent G
, and apply those changes to commit I
(where origin/whatever
points). Having copied J
to J'
, it then tries to copy K
to a new commit K'
, and so on. The eventual result, after you resolve any conflicts but before Git "peels the name off" commit L
, is:
J'-K'-L' <-- HEAD
/
...--F--G--H--I <-- origin/whatever
\
J--K--L <-- your-branch
The very last step of git rebase
is to remove the name your-branch
from where it is pasted right now, pointing to commit L
, and make it point instead to commit L'
—the last copy that rebase made:
J'-K'-L' <-- your-branch (HEAD)
/
...--F--G--H--I <-- origin/whatever
\
J--K--L [abandoned]
If you use git rebase --abort
instead of continuing, Git just abandons the copied chain instead, leaving the name your-branch
still pointing to L
:
J'-K'-L' [abandoned]
/
...--F--G--H--I <-- origin/whatever
\
J--K--L <-- your-branch (HEAD)
Before you start the rebase, or any time in the middle of the rebase when your-branch
still points to commit L
, you can add a new name to remember the raw hash ID of commit L
:
J'-K' <-- HEAD
/
...--F--G--H--I <-- origin/whatever
\
J--K--L <-- your-branch, extra-name
which you might do with git branch extra-name your-branch
for instance. That way, after you finish the rebase, assuming you do finish it, you end up with:
J'-K'-L' <-- your-branch (HEAD)
/
...--F--G--H--I <-- origin/whatever
\
J--K--L <-- extra-name
You don't have to do this, because secretly, git rebase
sets up a special name, ORIG_HEAD
, to remember where your branch name was before it yanked it off L
and pasted it onto L'
. But the name ORIG_HEAD
will be overwritten by whatever other Git command you use later (maybe another rebase) that yanks a label around like this, so that's sort of a short-term stop-gap you can use to recover if you don't like the result.
Your Git also records, in something called the reflog for the branch, the previous value of the branch name, i.e., the fact that your-branch
used to point to commit L
instead of L'
. These reflog entries last for 30 or 90 days.1 They're not the easiest things to use, though:
git reflog your-branch
will spill out all of them, but what you get is the one-line summary you used in each commit, and when you use git rebase
you generally copy the original one-line summary from commit L
to commit L'
, so it can be hard to tell which one is which.
Still, some combination of ORIG_HEAD
and the reflogs will usually let you recover without an extra name. Use the extra name if it makes you more comfortable. I do it a lot: if I am working on feature/X
, and need to rebase, I create feature/X.0
and then rebase. My original series of commits are now available as the dot-zero version. A few days later, if I need to do another rebase, I create feature/X.1
and then rebase. So feature/X
is the latest, and feature/X.<number>
is the older one, with more older ones remaining until I collect them up and toss them out myself.
1Technically, the ones that expire in 30 days are using the expireUnreachable
time: these are commits that are not reachable from the current value of the reference. Rebase generally makes this kind of reference, so the default 30 day expiration is the one you should concentrate on.
(Reflog entries that are reachable get the 90 day default.)
Upvotes: 2
Reputation: 2678
git rebase --abort
will just back out of the rebase entirely, essentially reverting your repository back to the point in time right before you started the rebase
. The only commits that are lost will be the brand new commits that git rebase
had created (since git rebase
replays your original commits, thus forming new commits).
The original commits are never touched regardless of whether you abort or not.
Upvotes: 0