160 lines
5.6 KiB
Markdown
160 lines
5.6 KiB
Markdown
|
+++
|
||
|
title = "Git! Rebase and Strategies"
|
||
|
author = ["Elia el Lazkani"]
|
||
|
date = 2019-08-10T21:00:00+02:00
|
||
|
lastmod = 2021-06-28T00:01:33+02:00
|
||
|
tags = ["git", "rebase", "strategies"]
|
||
|
categories = ["revision-control"]
|
||
|
draft = false
|
||
|
+++
|
||
|
|
||
|
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.
|
||
|
|
||
|
<!--more-->
|
||
|
|
||
|
|
||
|
## Requirements {#requirements}
|
||
|
|
||
|
This has not changed people, it is still _git_.
|
||
|
|
||
|
|
||
|
## Rebase {#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#%5Fbasic%5Fmerging) 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.
|
||
|
|
||
|
<div class="admonition note">
|
||
|
<p class="admonition-title">Note</p>
|
||
|
|
||
|
Branch and branch often!
|
||
|
if you merge, merge and merge often!
|
||
|
or rebase, and rebase often!
|
||
|
|
||
|
</div>
|
||
|
|
||
|
|
||
|
### Usage {#usage}
|
||
|
|
||
|
Rebase is used just like merge in our case.
|
||
|
|
||
|
First, let's create a branch and make a change in that branch.
|
||
|
|
||
|
```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.
|
||
|
|
||
|
```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.
|
||
|
|
||
|
```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.
|
||
|
|
||
|
```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.
|
||
|
|
||
|
```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 {#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 {#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.
|