Adding git rebase and strategies

This commit is contained in:
Elia el Lazkani 2019-08-10 23:32:15 +02:00 committed by Elia El Lazkani
parent 97e2714495
commit 9fb4a4ef70
No known key found for this signature in database
GPG key ID: FBD81F2B1F488C2B

View file

@ -0,0 +1,164 @@
.. title: Git! Rebase and strategies
.. date: 2019-08-10
.. slug: git-rebase-and-strategies
.. updated: 2019-08-10
.. status: published
.. tags: git, revision-control
.. category: revision-control
.. authors: Elijah Lazkani
.. 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.