owned this note
owned this note
Published
Linked with GitHub
---
title: Reproducible Research 5 - Git branches and in
tags: RR2025 - DS/QF
description:
slideOptions:
# theme: solarized
transition: 'slide'
---
<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

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

(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`

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`

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

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:

----
## New commits affect only the current branch

----
## New commits affect only the current branch

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`

----
## And add some commits while in there

----
## One more

----
## At any point you can return to the `main` with `git checkout main`

---
## 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`.

----
## While in `main` do `git merge feature`

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`).

----
## Now that we know the basics, let's look again
Can you trace what's been going on in this project?

(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

----
## Let's first move to the branch we want to move (`git checkout feature`)

----
## Then `git rebase main`

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:

----
## 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>`

----
## Let's go back to the large graph
Can you see how `rebase` could come in handy for the lower `feature` branch?

(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)

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`

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:

(and turn it into a new branch if you want to keep it)
---
## Assignment - imagine this is your repository

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).
---