2019-08-10 21:56:43 +00:00
|
|
|
.. title: Git! Rebase and Strategies
|
2019-08-10 21:32:15 +00:00
|
|
|
.. date: 2019-08-10
|
|
|
|
.. slug: git-rebase-and-strategies
|
|
|
|
.. updated: 2019-08-10
|
|
|
|
.. status: published
|
|
|
|
.. tags: git, revision-control
|
|
|
|
.. category: revision-control
|
2019-08-31 09:40:48 +00:00
|
|
|
.. authors: Elia El Lazkani
|
2019-08-10 21:32:15 +00:00
|
|
|
.. description: Getting a little handle on git rebase
|
|
|
|
.. type: text
|
|
|
|
|
|
|
|
In the previous topic, I talked about git remotes because it felt natural after branching and merging.
|
|
|
|
|
|
|
|
Now, the time has come to talk a little bit about ``rebase`` and some good cases to use it for.
|
|
|
|
|
|
|
|
.. TEASER_END
|
|
|
|
|
|
|
|
Requirements
|
|
|
|
============
|
|
|
|
|
|
|
|
This has not changed people, it is still ``git``.
|
|
|
|
|
|
|
|
Rebase
|
|
|
|
======
|
|
|
|
|
|
|
|
In ``git`` there are 2 ways of integrating your changes from one branch into another.
|
|
|
|
|
|
|
|
|
|
|
|
We already talked about one; ``git-merge``. For more information about ``git-merge`` consult
|
|
|
|
the `git basic branching and merging <https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#_basic_merging>`_
|
|
|
|
manual.
|
|
|
|
|
|
|
|
|
|
|
|
The other is ``git-rebase``.
|
|
|
|
|
|
|
|
While ``git-rebase`` has a lot of different uses,
|
|
|
|
the basic use of it is described in the `git branching rebasing <https://git-scm.com/book/en/v2/Git-Branching-Rebasing>`_
|
|
|
|
manual as:
|
|
|
|
|
|
|
|
"With the ``rebase`` command, you can take all the changes
|
|
|
|
that were committed on one branch and replay them on
|
|
|
|
a different branch."
|
|
|
|
|
|
|
|
In other words, all the commits you have made into the branch you are on will be set aside.
|
|
|
|
Then, all the changes in the branch you are rebasing from will be applied to your branch.
|
|
|
|
Finally, all your changes, that were set aside previously, will be applied back to your branch.
|
|
|
|
|
|
|
|
The beauty about this process is that you can keep your branch updated with upstream,
|
|
|
|
while coding your changes. By the end of the process of adding your feature, your changes are
|
|
|
|
ready to be merged upstream straight away. This is due to the fact that all the conflicts
|
|
|
|
would've been resolved in each rebase.
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
Branch and branch often!
|
|
|
|
|
|
|
|
if you merge, merge and merge often!
|
|
|
|
|
|
|
|
or rebase, and rebase often!
|
|
|
|
|
|
|
|
Usage
|
|
|
|
-----
|
|
|
|
|
|
|
|
Rebase is used just like merge in our case.
|
|
|
|
|
|
|
|
First, let's create a branch and make a change in that branch.
|
|
|
|
|
|
|
|
.. code:: text
|
|
|
|
|
|
|
|
$ git checkout -b rebasing-example
|
|
|
|
Switched to a new branch 'rebasing-example'
|
|
|
|
$ printf "\n# Rebase\n\nThis is a rebase branch.\n" >> README.md
|
|
|
|
$ git add README.md
|
|
|
|
$ git commit -m "Adding rebase section"
|
|
|
|
[rebasing-example 4cd0ffe] Adding rebase section
|
|
|
|
1 file changed, 4 insertions(+)
|
|
|
|
$
|
|
|
|
|
|
|
|
Now let's assume someone (or yourself) made a change to the ``master`` branch.
|
|
|
|
|
|
|
|
.. code:: text
|
|
|
|
|
|
|
|
$ git checkout master
|
|
|
|
Switched to branch 'master'
|
|
|
|
Your branch is up to date with 'origin/master'.
|
|
|
|
$ printf "# Master\n\nThis is a master branch" >> master.md
|
|
|
|
$ git add master.md
|
|
|
|
$ git commit -m "Adding master file"
|
|
|
|
[master 7fbdab9] Adding master file
|
|
|
|
1 file changed, 3 insertions(+)
|
|
|
|
create mode 100644 master.md
|
|
|
|
$
|
|
|
|
|
|
|
|
I want to take a look at how the tree looks like before I attempt any changes.
|
|
|
|
|
|
|
|
.. code:: text
|
|
|
|
|
|
|
|
$ git log --graph --oneline --all
|
|
|
|
* 7fbdab9 (HEAD -> master) Adding master file
|
|
|
|
| * 4cd0ffe (rebasing-example) Adding rebase section
|
|
|
|
|/
|
|
|
|
* 4f6bb31 (origin/master) Adding the git remote section
|
|
|
|
* 0bd01aa Second commit
|
|
|
|
|
|
|
|
After both of our commits, the tree diverged.
|
|
|
|
We are pointing to the ``master`` branch, I know that because ``HEAD`` points to ``master.
|
|
|
|
That commit is different than the commit that ``rebase-example`` branch points to.
|
|
|
|
|
|
|
|
These changes were introduced by someone else while I was adding the rebase section
|
|
|
|
in the ``README.md`` file and they might be crucial for my application. In short,
|
|
|
|
I was those changes in the code I am working on right now. Let's do that.
|
|
|
|
|
|
|
|
.. code:: text
|
|
|
|
|
|
|
|
$ git checkout rebasing-example
|
|
|
|
Switched to branch 'rebasing-example'
|
|
|
|
$ git rebase master
|
|
|
|
First, rewinding head to replay your work on top of it...
|
|
|
|
Applying: Adding rebase section
|
|
|
|
|
|
|
|
And, let's look at the tree of course.
|
|
|
|
|
|
|
|
.. code:: text
|
|
|
|
|
|
|
|
$ git log --graph --oneline --all
|
|
|
|
* 1b2aa4a (HEAD -> rebasing-example) Adding rebase section
|
|
|
|
* 7fbdab9 (master) Adding master file
|
|
|
|
* 4f6bb31 (origin/master) Adding the git remote section
|
|
|
|
* 0bd01aa Second commit
|
|
|
|
|
|
|
|
The tree lookr linear now. ``HEAD`` is pointing to our branch.
|
|
|
|
That commit points to the ``7fbdab9`` commit which the ``master`` branch
|
|
|
|
also points to. So rebase set aside ``1b2aa4a`` to apply ``7fbdab9`` and then
|
|
|
|
re-applied it back. Pretty neat huh ?!
|
|
|
|
|
|
|
|
My Strategy
|
|
|
|
===========
|
|
|
|
|
|
|
|
I'm going to be honest with you. I do not know the different kinds of merge strategies.
|
|
|
|
I've glazed at names of a few but I've never looked at them closely enough to see which one is what.
|
|
|
|
|
|
|
|
What I use, I've used for a while. I learned it from somewhere and changed a few things in it to make it work for me.
|
|
|
|
|
|
|
|
First of all, I always fork a repository.
|
|
|
|
I tend to stay away from creating a branch on the upstream repository unless it's my own personal project.
|
|
|
|
On my fork, I freely roam. I am the king of my own fork and I create as many branches as I please.
|
|
|
|
|
|
|
|
I start with an assumption. The assumption is that my ``master`` branch is, for all intents and purposes,
|
|
|
|
upstream. This means I keep it up to date with upstream's main branch.
|
|
|
|
|
|
|
|
When I make a branch, I make a branch from ``master``, this way I know it's up to date with upstream.
|
|
|
|
I do my work on my branch. Every few hours, I update my ``master`` branch. After I update my ``master``
|
|
|
|
branch, I ``rebase`` the ``master`` branch into my branch and voilà I'm up to date.
|
|
|
|
|
|
|
|
By the time my changes are ready to be merged back into upstream for any reason, they are ready to go.
|
|
|
|
|
|
|
|
That **MR** is gonna be ready to be merged in a jiffy.
|
|
|
|
|
|
|
|
Conclusion
|
|
|
|
==========
|
|
|
|
|
|
|
|
From what I've read, I use one of those strategies described on some website. I don't know which one.
|
|
|
|
But to me, it doesn't matter because it works for me. And if I need to adapt that for one reason or another,
|
|
|
|
I can.
|