#+BEGIN_COMMENT .. 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: Elia el Lazkani .. description: Getting a little handle on git rebase .. type: text #+END_COMMENT 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 [[https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#_basic_merging][git basic branching and 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 [[https://git-scm.com/book/en/v2/Git-Branching-Rebasing][git branching rebasing]] manual as: #+BEGIN_QUOTE "With the =rebase= command, you can take all the changes that were committed on one branch and replay them on a different branch." #+END_QUOTE 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. #+BEGIN_EXPORT html

Note

#+END_EXPORT Branch and branch often! if you merge, merge and merge often! or rebase, and rebase often! #+BEGIN_EXPORT html
#+END_EXPORT ** Usage Rebase is used just like merge in our case. First, let's create a branch and make a change in that branch. #+BEGIN_EXAMPLE $ 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(+) $ #+END_EXAMPLE Now let's assume someone (or yourself) made a change to the =master= branch. #+BEGIN_EXAMPLE $ 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 $ #+END_EXAMPLE I want to take a look at how the tree looks like before I attempt any changes. #+BEGIN_EXAMPLE $ 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 #+END_EXAMPLE 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. #+BEGIN_EXAMPLE $ 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 #+END_EXAMPLE And, let's look at the tree of course. #+BEGIN_EXAMPLE $ 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 #+END_EXAMPLE 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.