3

I've created a branch for experimentation. I've decided it was the direction I want to take, so want to put the changes into the master.

I don't want to merge, I'd prefer rebase, as this sounds exactly what I want (it to be like I was using master all along).

Looking at the documentation, it seems pretty simple (this is instruction from the docs):

However, there is another way: you can take the patch of the change that was introduced in C4 and reapply it on top of C3. In Git, this is called rebasing. With the rebase command, you can take all the changes that were committed on one branch and replay them on another one.

In this example, you’d run the following:

$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command

'experiment' in my case is the branch 'denormalized' which is already checked out (output from my console):

$ git status
On branch denormalized
Your branch is up-to-date with 'origin/denormalized'.
nothing to commit, working tree clean

Now, I call git rebase master:

$ git rebase master
Current branch denormalized is up to date.

Okay, so that's not what I'm expecting according to the documentation. There also seems to be no changes to either branch:

enter image description here

The master is still what it was before the rebase. I can check it out and nothing has changed.

What am I missing?

Community
  • 1
  • 1
Joe
  • 6,773
  • 2
  • 47
  • 81
  • From master branch, `git merge --ff-only experiment` It will not create a merge node, it will just advance `master` (the `--ff-only` flag forces the command to fail if the branches have diverged and it would create a merge node) – spectras May 22 '17 at 13:52
  • I'll note that I initially found your question very confusing because I thought you had actually run `git checkout experiment` and were quoting your own session, rather than the linked documentation. :-) As for what rebase really does, well, see (e.g.) https://stackoverflow.com/a/39833386/1256452 – torek May 22 '17 at 14:10
  • @torek I've tried to clarify (in case this is useful for future users). I always try use quotes ">" for things like that, but it never plays well with console output or multi-line formatting, only paragraph/text quotations. – Joe May 23 '17 at 09:13
  • There is a weird tricky thing with SO quoting: four space indent = literal text, `>` prefix = quote, but `>foo` and `> foo` both work and the space gets eaten. Hence when mixing `>` with literal indent you need FIVE spaces because one gets eaten (!). – torek May 23 '17 at 09:27
  • @torek, ah! that's good to know, I've always got frustrated quoting code. – Joe May 23 '17 at 09:30
  • One other useful trick (not needed here, and one that's a pain if you use control-K to indent, but I thought I'd mention them): if you're in a bullet or numbered list and want to have literal text you need *eight*, not just four, spaces. – torek May 23 '17 at 09:36

2 Answers2

6

While Matt Clark's answer is a correct procedure for your current situation, I think it leaves a couple things unclear; so I'll add the following:

The rebase command you issued is correct, but it doesn't do exactly what you think. If you had

A --- B --- C <--(masteR)
       \
        D --- E <--(branch)

(so master has moved on since the branch point for branch), and you want to combine branch into master without a merge commit, then a rebase would be the first step.

git checkout branch
git rebase master

(or the shorthand git rebase master branch). This gives

A --- B --- C <--(masteR)
             \
              D' --- E' <--(branch)

and now a fast-forward merge (combining branch into master without a merge commit) is possible whereas before it was not. To cause the fast-forward you can either

git checkout master
git merge branch

(which will do a fast-forward because it can), or while still on branch

git branch -f master

which simply forces the master branch to move to where you are (and is generally a more dangerous command but has the same effect here).

In your case, because the branch is already rooted at the tip of master, the rebase is unnecessary and you can move straight to the ff merge.

Note that if you are sharing branches with other developers (e.g. through a remote repository) and it's possible that they're using a branch (e.g. because you've pushed it), then you should be careful about rebasing that branch (i.e. you need to coordinate with the other developers to do it). See "recovering from upstream rebase" in the git rebase documentation. https://git-scm.com/docs/git-rebase

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • Thank you, that's exactly what I needed to understand. I have used rebase on a single branch to 'windback' to an earlier commit so was confused that it had (a misunderstood) dual use. When the document says "First, rewinding head to replay your work on top of it..." the "to replay your work on top of it" is referring to the future merge. Rebase is just the 'rewinding' part - which I didn't actually need. Thanks for the detailed explanation. – Joe May 23 '17 at 09:08
5

To get these changes into master, what you need to do it:

git checkout master
git merge denormalized

The merge will pull those changes into your branch.

What the rebase does, it chain those commits off of head, but still on your other ref.

After the merge, you should end up with both master and denormalized HEADs at -Refactored the generator...

It shows you to do this right above figure 37

Matt Clark
  • 27,671
  • 19
  • 68
  • 123
  • 1
    This is what I meant in my comment ^^. You can add `--ff-only` to be sure not to inadvertently create a merge node if `master` does not point to an ancestor of `denormalized`. – spectras May 22 '17 at 13:55
  • Looks like I've totally misunderstood rebase. Could you expand a little on what you mean by "chain those commits off of head, but still on your other ref"? – Joe May 22 '17 at 13:58
  • I think we posted with seconds of eachother :p You should have just added that an an answer. – Matt Clark May 22 '17 at 13:58
  • A rebase, changes the parent of the commits. All you do is move the commits to a new parent, but they are still on their own branch. Now the merge will pull them into the master branch. Meeting, gotta run :O – Matt Clark May 22 '17 at 13:59
  • @Joe> If you visualize your git tree, `rebase` is pulling the branch off and gluing it at some other place. It's still an independent branch though. _(that's only for visualization as the rebase process does not really move the commits, it duplicates them - old ones will be garbage collected eventually)_. – spectras May 22 '17 at 14:04