changed 3 months ago
Published Linked with GitHub

Git: Branches, merging, rebasing

Wojciech Hardy

link: https://hackmd.io/@WHardy/RR25-git4


Branches

Part of the typical workflow


Source: Harness


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)


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.

  1. As dev1 create a short history of commits (minimum two) and push them

  1. As dev2 pull the information

Let's practice branching

  1. As Dev1, create a new branch named feature1

  1. List branches (try to find the appropriate git branch option to do that)

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


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

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


  1. As Dev2 execute git pull and check git branch -l

  1. Execute git checkout feature1 and check git branch -l again

Let Dev2 do some work

  1. Create a new commit on the main branch

  1. Create a new commit on the feature1 branch

  1. Run git status on the main branch, push the changes

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


Let's go back to the terminal

  1. As Dev1 get all the newest updates for both branches.

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


Other fun stuff: detaching HEAD

  1. What if we move our HEAD?

Check this tutorial for an easy step-by-step description (the image comes from there)

Or try this one if you like X-Men - 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

obraz

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


For more on rebasing.

Read Merging vs rebasing on Atlassian for a nice description of both approaches (also their individual pages).

Also, take a look at git bisect, to understand when rebasing might be helpful.

Also, take a look at git stash.


Select a repo