- [Cameron] Hey, I'm Cameron MacKenzie.
I'm the editor in chief over theserverside.com.
You can follow me on Twitter cameromcnz,
and I wanted to talk to you about doing a rebase.
And in this example, I want to show you how
to do a rebase to master.
Specifically I'm going to take my develop branch
and merge it into the master branch,
but not by using a merge, but by using a rebase.
And of course the big distinction here,
is when I do a rebase,
I end up changing the commit history.
So if you look here,
this is the current branch that I'm using.
You can find this I've got an account at GitHub
and GitLAb that has this.
You can fork it and do this exercise yourself,
I really recommend that.
But the basic repository goes like this.
There are five commits in the master branch,
A, B, C, D and E.
And then after branch C,
we actually moved into a split for the develop branch
and the develop branch has commit F and G on it.
Now in each commit,
we create a brand new HTML file
that maps to the name of the commit.
So you can see that at commit number E,
the master branch has files a, b, c, d, and e in it,
right that maps to the history of the master branch.
But after the develop branch split off from C,
it added F and G commits,
which means it has the f and g .html files in it.
The master branch does not have F and G
because it was not a party to those particular commits.
And the develop branch does not have D and E
because it was not a party to those commits
on the master branch.
And so the goal here is to rebase develop onto master,
which means we now take this commit G
and we reverse the entire branch history here
and stick that F commit at the end of E.
That will give us D and E in the develop branch,
and we end up with all seven files,
when the rebase occurs successfully.
And so you can see here,
that's the original graph structure
of the repository when we're done it becomes very,
very linear.
We take that develop branch and we put G and F,
right at the end of E.
And you can kind of see a listing of all
of the different files in the bottom here.
After the rebase,
we have a very linear type of branching here.
The only place we have a branch is
after the tip of the master branch,
and that's where the develop branch comes off.
And you can see that the master branch, when we're done,
it remains with the same set of files
that it had originally.
Nothing changes with the master branch,
other than the fact that nobody is splitting off
from commit number C.
Instead the branch, the split happens at commit E,
that's where anybody looking
at this repository will see the branching
of develop, and also develop because it's now stuck
at the end of the E branch, get all of the files in E.
And so at the end, the develop branch has seven files in it,
all of the files it started with plus the D and the e files.
Now here's how we do it in code.
I would really like you to follow along on this example.
So you can actually just fork this project. It's
at gitlab.com/cameronmcnz/simple-rebase-and-merge-example.
It's also on GitHub, same URL,
except github.com, and all you have to do is go
to the project and just you'll see a fork button
and just fork it into your own GitLab
or GitHub repository, and then you can clone it.
So I've already done that,
I got a separate account called jhegavera here.
It has forked the simple rebase and merge
and I'm just going to clone that whole repository
and bring it down to my local file system.
(keys clacking)
Now I have to CD into that folder.
And the other thing that you need to do,
you just need to make sure
that you've got both branches locally,
and I have to do that by doing a git-checkout
of the developer branch, and that's just called develop.
So branch develop has now been checked out.
You know, it's also interesting if you want,
just do a Git log graph. (keys clacking)
And it'll actually show you the,
what the actual repository looks like
and you can see here,
everything that has mas after it was part
of the master branch commit,
and then anything that has dev after it,
was part of the dev branch commit.
And so you can kind of see here is the master branch
and then that's part of the master as well as,
as is this and then these two commits are part
of the dev branch.
So what I want to do is I want to do that rebase.
So I want to come in and I want
to take the developer branch right here
and rebase it onto the top
of the master branch right there E.
Not too hard to do,
all I have to do is issue the git rebase command,
and master is going to be what we're rebase onto.
And the branch that we want to rebase is called develop.
And that's all we have to do in order to issue the command.
Now I'm actually not going to do it now.
I'm just going to check my status,
(keys clacking)
and I'm on the develop branch.
And I want you to see that I've got one, two, three,
four, five files here,
a, b, c, f, g, but I'm missing d and e.
And d and e are part of the master branch
and so if I issue this, get rebase command,
the rebase is going to work,
the history is going to be changed
and now you can actually see, you know,
it looks like it's kind of reversed a few things,
and it's now putting F and G commits back on top of master.
Bottom line is if I now do an ls command,
you'll notice that I've got two new files,
a, b, c, d, e, f and g.
And if I take a look at my git log history
in graph format,
you'll see that I've got a very, very flat git log graph,
I've got a very flat history.
And this history is telling me that, you know what?
There were one, two, three, four, five commits
on the master branch, A, B, C, D and E,
there's no on the initial commit,
but these are the ones I'm concentrating on,
a, b, c and d and e.
And then, then it says, oh, and then after e,
develop came along, did a branch
and then applied commit F and G.
And that's not what happened, right?
If you actually look at the previous graph,
you'll see that the develop branch,
actually branched off after c.
So we've actually rewritten the entire history here.
We've rewritten the whole, the whole history of,
of the master branch and the develop branch.
But also notice, even though these,
these commits have the same name f dev and g dev,
if we actually go up here and take a look at the commit IDs,
you'll see, that starts with b7 and f7.
You notice that originally,
those two commits don't have the same commit IDs.
So it's not only kind of changed the history,
but it hasn't just moved commits around.
It's actually deleted the old commits
and then created brand new commits with new commit IDs.
So that's what's going on here.
You're not getting this scenario,
where what was previously this F and G branch,
which was branching off of C,
now we actually have F and G,
put onto the tip of E.
And in that process, F and G now are getting applied
to a commit that has d and e in it.
And so now at the end, this develop branch has
a, b, c, d, e, f and g in it.
It's got all of the files,
whereas opposed it only had five before.
Now the thing is e isn't changed,
we didn't do any changes with e.
So if I come back into my git repository
and do a check-out of master
and do the ls command, you'll see
that master still has the five files in it
that it started off with.
Now let's get back to develop.
Okay. So that all seems to have worked properly.
So there you go, that's the whole idea of a rebase.
One thing that is worth mentioning,
if you ever try and push your changes back
to get where you try and push your changes back to GitHub,
you're going to get some flack for it.
Especially if you've done a rebase on,
on branches that originally came from a remote repository
and other users may have them.
You're supposed to only do rebases
on local topic branches, on local development.
You shouldn't do it with branches
that other people are using, because it's going
to cause a whole lot of trouble.
However, if you do want it,
well, let me show you what happens if I try
and do a git push origin of a master branch.
Let's see what happens.
Ask for my username. (keys clacking)
Now let me do git push well.
It's the develop branch that changed, right?
Notice that as I try and push the develop branch,
I get a lot of static.
I did the master branch first,
but of course the master branch hasn't changed.
So it doesn't mind a push to the master branch.
But if you're now going to push that develop branch,
it's going to say, hey, this is going to be rejected.
We don't like this at all.
You're doing some crazy branch changing history,
commit stuff, not going to accept it.
So you can actually do a forced switch on here
and actually force the server to take it.
(keys clacking)
And so now that force has,
has pushed that up and I can now go up to this particular,
git lab repository, jehgavera.
I'll take a look at the graph,
and you'll notice now the graph has changed, right?
We've got developed off master,
so that's a pretty significant change right there.
But by default, GitHub, GitLab,
they don't want to take the changes after a rebase.
And the reason is if somebody else now comes in here
and tries to do a pull and emerge these changes,
some of their commits are going to be gone,
new commits are there, the branch point
of the develop branch isn't the same branch point
as their developed branch and all sorts of problems can,
can happen.
So, you know, that's just a caveat.
Be very, very careful when you do a rebase.
So I really hope
that gave you a good idea about how the git rebase
to master works.
Now, if you enjoyed this tutorial,
head over to theserveride.com.
I'm the editor in chief over there,
and we've got lots of great articles and tutorials
on Git, GitHub, DevOPs tools and all sorts of stuff
that has to do with enterprise software development.
Also, if you're interested in my personal antiques,
you can follow me on Twitter @cameronmcnz.
Oh, and subscribe on YouTube.