git rebase basics
Solution 1
Let's start from the beginning. Here's a diagram of your original state:
A-B-C (master, origin/master) \ D-E-F-G-H-I (next, origin/next)
When you checked out next
and rebased next
onto origin/master
, it created 6 new commits after the two that are already on origin/master
. These new commits have "master commit #2" (C
in my diagram) as their ancestor, not their original ancestor where origin/master
and origin/next
diverged (A
in my diagram), so their hashes will be different. I believe this is why you'll see that next
has 8 different commits from origin/next
: the 2 from origin/master
and the 6 "rehashed" commits that were on origin/next
.
After git checkout next ; git rebase -i origin/master
, you should have this:
A-B-C (master, origin/master) \ \ \ D'-E'-F'-G'-H'-I' (next) \ D-E-F-G-H-I (origin/next)
You can see that next
does have 8 commits that aren't on origin/next
, and origin/next
does have 6 commits that aren't on next
. Granted this is just according to the SHA-1 hashes of the commits. The actual content should match very closely if you git diff origin/next next
-- the diff should just show the changes from B
and C
(as labeled in the diagram).
When you do git pull --rebase
while still on next
, it fetches changes from the source (the remote origin/next
) and rebases the current branch (next
) onto that remote. This causes the changes that were in the next
but not in origin/next
to appear after origin/next
on the new next
branch. It should look like this:
A-B-C (master, origin/master) \ D-E-F-G-H-I (origin/next) \ B'-C' (next)
If this is what you wanted the history graph to look like, then you've succeeded.
However, I suspect you really wanted things to look like the middle diagram, especially if next
is a feature branch where you're working on the next piece of the project and master
is for stable code and small bug fixes. If so, then you should have done git push
instead of git pull --rebase
to make the remote reflect your version of history instead of the other way around.
Solution 2
Start with the very simple steps for rebasing your branch with the master; Name;
git-rebase
Synopsis;
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
[<upstream>] [<branch>]
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
--root [<branch>]
git rebase --continue | --skip | --abort | --edit-todo
Description; Assume the following history exists and the current branch is "sample":
A---B---C sample
/
D---E---F---G master
From this point, the result of either of the following commands:
git rebase master
git rebase master sample
would be:
A'--B'--C' sample
/
D---E---F---G master
NOTE: The latter form is just a short-hand of git checkout sample
followed by git rebase master
. When rebase exits sample will remain the checked-out branch.
If the upstream branch already contains a change you have made (e.g., because you mailed a patch which was applied upstream), then that commit will be skipped. For example, running ‘git rebase master` on the following history (in which A’ and A introduce the same set of changes, but have different committer information):
A---B---C sample
/
D---E---A'---F master
will result in:
B'---C' sample
/
D---E---A'---F master
All these were the diagramatic understanding of the rebase process.
Once you resolve the conflicts being found after typing git rebase master
resolve the conflicts and type git add -u
to add the changed codes to the repository.
after that perform the command git rebase --continue
and continue resolving the conflicts and and repeating the command ;
git add -u
and
git rebase --continue
until no conflicts being found. At last the final command will be ,
git push --force origin sample(your branch name)
Comments
-
David Kuridža about 2 years
I have started using
git rebase
recently and am not 100% certain I'm doing it right. For the sake of the question, there are two branches in origin,master
andnext
, which was branched frommaster
.Since last sync between the two,
master
had 2 commits andnext
6:$ git log --oneline origin/next..origin/master 59b5552 master commit #2 485a811 master commit #1 $ git log --oneline origin/master..origin/next 4ebf401 next commit #6 e9b6586 next commit #5 197ada0 next commit #4 4a2c3c6 next commit #3 040a055 next commit #2 84537bf next commit #1
When I checkout
next
and executegit rebase -i origin/master
, I get the following:$ git status # On branch next # Your branch and 'origin/next' have diverged, # and have 8 and 6 different commits each, respectively.
And finally after doing
git pull --rebase
, the two commits frommaster
are innext
:$ git log --oneline origin/next..next 8741d09 master commit #2 485a811 master commit #1
Questions:
- Is this correct approach?
- Why are there
8 and 6
different commits untilpull --rebase
is run? - Is it possible to simplify the flow?
Much obliged :)
-
Seth Robertson almost 12 yearsI assume
git rebase --pull
is much likegit pull --rebase
. It does a fetch and then agit rebase @{u}
Well, that's a lie, but it is an easy way to think about it. But the point is that your local branch is reset to @{u} and then all local commits on your old branch before the reset are replayed on top of what upstream has. This allows a trivial fastforward push upstream. -
Mike Seplowitz almost 12 yearsAssuming
git rebase --pull
was a typo and should have beengit pull --rebase
, then I think that would reordernext
intoD'-E'-F'-G'-H'-I'-B'-C'
. Does that sound right? If so, I'll edit my answer accordingly. -
Seth Robertson almost 12 yearsAfter
git pull --rebase
you will get A-D-E-F-G-H-I-B'-C'. The g-p-r will always force your local branch (next) to contain all of the commits on @{u} (origin/next) and then anything which is unique to next will be replayed (probably cherry-picked) on top. Congratulate git for being smart enough to not attempt to create D"-E"-F"-G"-H"-I" -
David Kuridža almost 12 yearsReally sorry for the typo, it should be
git pull --rebase
. Thank you for the explanation, I now understand what happens. Is the flow I'm doing correct?git rebase
and thengit pull --rebase
or is there some other way? -
Seth Robertson almost 12 years@DavidKuridža: There is no particular reason why you need to do either command. If next was at ADEFGHI and your goal is ADEFGHIB'C' then the only command you need to run is
git checkout next; git cherry-pick ...master
-
Mike Seplowitz almost 12 yearsDavid, I think
rebase
followed bypull --rebase
is self-defeating, since it changes the history in one direction and then goes back the other way. The real question to answer before you run any commands (other thangit fetch
to updateorigin/*
) is: What do I want the history to look like when I'm done? Once you know that, then the actions you take should lead towards that goal. -
David Kuridža almost 12 yearsIt turned out my understanding of rebase was wrong, thanks to all these comments I believe it should be fine now. I am really grateful to all of you!
-
Sam over 10 yearsfor external refernce follow kernel.org/pub/software/scm/git/docs/git-rebase.html
-
chill appreciator over 3 yearsPlease realign your diagrams to make it clear