<style> .reveal { font-size: 26px; } </style> ## Git: Branches, merging, rebasing Wojciech Hardy link: https://hackmd.io/@WHardy/RR25-git4 --- ## Branches Part of the typical workflow ![](https://i.imgur.com/gUWMU0q.png) Source: [Harness](https://www.harness.io/blog/git-branching) --- ## Branches -- advantages Main branch keeping a clean history of releases Room for experimentation without breaking anything Simultaneous work for many people Easy to reverse work on a feature and continue with main Separate teams can work at the same time on: larger patches, hotfixes, new features, optimisation, etc. --- ## Branches can have branches ![](https://i.imgur.com/9G6xsil.png =600x) (Source: [Git Better](https://gitbetter.substack.com/p/how-to-work-in-multiple-git-branches)) --- ## Branches - how do they work? Recall `master` or `main` branch is an indicator You create a new branch using `git branch <branch-name>` The new branch is a new indicator with its own `staging area` and `working directory` Scroll down to see what happens step-by-step ---- ## We start with one branch: `main` ![](https://i.imgur.com/mtTy9kH.png) Recall: `HEAD` points to 'where we currently are' `main` points to the latest commit on branch ---- ## We create a new branch that we name "feature" with `git branch feature` ![](https://i.imgur.com/gnxYmVD.png) This creates a new indicator pointing to where we are. But `HEAD` still points to the `main` branch. ---- ## We use `git checkout feature` to get to the new "feature" branch ![](https://i.imgur.com/u3DVeC4.png) The `HEAD` indicator goes to the `feature` branch. --- ## Commands `git branch [-l]` list/create/delete branches `git checkout` move the HEAD pointer (switch between branches) `git fetch` sync cached branches with remote `git rebase [x]` make a branch [x] start from a different point `git merge [x]` combine two branches (by joining [x] to the current) --- ## Ok, let's do it, setup: 1) In folder RR_git4 create bare central repository and two cloned ones. ---- 2) As `dev1` create a short history of commits (minimum two) and push them ---- 3) As `dev2` pull the information --- ## Let's practice branching 1) As Dev1, create a new branch named `feature1` ---- 2) List branches (try to find the appropriate `git branch` option to do that) ---- 3) Switch to the new branch (use `git checkout <branch-name>`) --- ## What's the new workflow? You can add commits only to one of the branches at a time. When you switch between branches, Git 'refreshes' your staging area and working directories to match `HEAD`. --- ## Let's start with a simple commit history: ![](https://i.imgur.com/UJfRiNf.png) ---- ## New commits affect only the current branch ![](https://i.imgur.com/F0hSnDf.png) ---- ## New commits affect only the current branch ![](https://i.imgur.com/V4BkVu4.png) In a big project, e.g. if you're the one working on the `feature`, changes to `main` might not be yours (other people push their features/fixes, etc. in the meantime). ---- ## Let's switch to the `feature` branch with `git checkout feature` ![](https://i.imgur.com/Ii677W9.png) ---- ## And add some commits while in there ![](https://i.imgur.com/yph7crB.png) ---- ## One more ![](https://i.imgur.com/CH0mZFn.png) ---- ## At any point you can return to the `main` with `git checkout main` ![](https://i.imgur.com/xp7F7GK.png) --- ## Let's try working with branches 1) As Dev1, while in the `feature1` branch, add a file, stage and commit it. Then do a `push`. Read the message and follow the hints. ---- 2) Switch back to the `main` branch and check what's going on in your working directory (e.g. in File explorer in Windows or Finder in MacOS). ---- 3) Add a file (do not commit it) and try changing branches. What happens? (put it somewhere as part of a new commit and push it) ---- 4) As Dev2 execute `git pull` and check `git branch -l` ---- 5) Execute `git checkout feature1` and check `git branch -l` again --- ## Let Dev2 do some work 1) Create a new commit on the `main` branch ---- 2) Create a new commit on the `feature1` branch ---- 3) Run `git status` on the `main` branch, push the changes ---- 4) Run `git status` on the `feature1` branch, push the changes --- ## There are two main ways of putting the results back together You might recall `merge` from how we united `main` with `origin/main`. ![](https://i.imgur.com/3yJ2iE8.png) ---- ## While in `main` do `git merge feature` ![](https://i.imgur.com/QoluIh0.png) Recall: `merge` creates a new commit. ---- ## You can still work on your `feature` branch It doesn't include the merge (unless you also do `git merge main` while on the branch `feature`). ![](https://i.imgur.com/RwCSUiK.png) ---- ## Now that we know the basics, let's look again Can you trace what's been going on in this project? ![](https://i.imgur.com/9G6xsil.png =600x) (Source: [Git Better](https://gitbetter.substack.com/p/how-to-work-in-multiple-git-branches)) --- ## Let's go back to the terminal 1) As Dev1 get all the newest updates for both branches. ---- 2) Merge the `feature1` branch to the `main` branch using `git merge <branch-name>`. Push. Conflict resolution is the same as we once did. --- ## The second approach is rebasing Rebasing is making your branch start from a different point ![](https://i.imgur.com/NLfjohh.png) ---- ## Let's first move to the branch we want to move (`git checkout feature`) ![](https://i.imgur.com/CH0mZFn.png) ---- ## Then `git rebase main` ![](https://i.imgur.com/rZVs88x.png) Important: `rebase` destroys original commits and creates new ones! Probably not a good thing if the original ones were shared with others or in a remote repository! --- ## Also, you don't need to rebase only within the same branch Assume you start with this: ![](https://i.imgur.com/nAkSXAw.png) ---- ## Possible troublesome situations: - `feature1` branch proved a dead end, but `feature2` is promising - `feature2` is actually unrelated to `feature1` - `main` branch introduced something relevant to `feature2` ---- ## The solution is to rebase `feature2` to `main` `git checkout feature2` `git rebase --onto main feature1 feature2` `git rebase --onto <new-base> <old-base> <moved-branch>` ![](https://i.imgur.com/9DqWc03.png) ---- ## Let's go back to the large graph Can you see how `rebase` could come in handy for the lower `feature` branch? ![](https://i.imgur.com/9G6xsil.png =600x) (Source: [Git Better](https://gitbetter.substack.com/p/how-to-work-in-multiple-git-branches)) --- ## Other fun stuff: detaching HEAD 1) What if we move our HEAD? Check [this tutorial for an easy step-by-step description](https://www.cloudbees.com/blog/git-detached-head) (the image comes from there) ![](https://i.imgur.com/OEZDXFS.png =600x) Or [try this one if you like X-Men](https://hashrocket.com/blog/posts/x-men-days-of-future-past-explained-in-git) - it's actually helpful (if you watched Days of Future Past)! Typically HEAD points to the branch ("you're currently here"). ---- ## Answering questions from last week You can point it to an older commit instead: `git checkout 87ec91d` ![](https://i.imgur.com/4K9THmq.png) This puts you in a "detached HEAD state". ---- ## Answering questions from last week Here you can: 1) panic and go back simply by redirecting it back to the branch, e.g. `git checkout master` 2) check what was done in this commit 3) create an alternate history: ![](https://i.imgur.com/9qlCKL6.png =600x) (and turn it into a new branch if you want to keep it) --- ## Assignment - imagine this is your repository ![obraz](https://hackmd.io/_uploads/r1cHiXvAT.png =600x) You do the following: 1) Rebase the Hotfix branch onto Main. 2) Create a new commit on the Main branch. 3) Merge Hotfix branch with the Main branch. 4) Rebase Feature1 onto Main. What's the new situation? Draw it on a piece of paper or send me a photo :) --- ## Helpful links [For more on rebasing](https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase). Read [Merging vs rebasing on Atlassian](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) for a nice description of both approaches (also their individual pages). Also, take a look at [`git bisect`](https://git-scm.com/docs/git-bisect), to understand when rebasing might be helpful. Also, take a look at [`git stash`](https://git-scm.com/docs/git-stash). ---
{"title":"Reproducible Research 5 - Git branches","slideOptions":"{\"transition\":\"slide\"}","description":"Wojciech Hardy","contributors":"[{\"id\":\"1c10bb23-6c4c-4c1b-8586-5f8d56305139\",\"add\":9093,\"del\":409}]"}
    742 views