Average rainfall 2001-2016, global tropics

Map: Average rainfall 2001-2016, global tropics

git branches

Thomas Gumbricht bio photo By Thomas Gumbricht

NOTE, 1 October 2020 the label ‘master’ was replaced by ‘main’ for the default repo branch.

Introduction

This post covers git branches. The main references for this post are the Atlassian Bitbucket pages on git branches and the Youtube Introduction to Git - Branching and Merging by David Mahler.

Prerequisites

This tutorial is a continuation of my posts on Local git control and Shared master local git control.

Create new repo

The post on Local git control introduced git repositories (repos) as directories with added functions. Open a Terminal window and navigate to the parent folder where you want to create your repository for this hands-on tutorial, then execute the following commands:

$ mkdir git-test-repo
$ cd git-test-repo
$ git init
$ pico README.md

and add a message to the README.md file:

Test repository for branching

Hit [ctrl]+[X] to exit pico and save the edits by pressing Y when asked.

Add another text file, for example Chapters.md ($ pico Chapters.md), add some lines of text and save and exit. In my example I added the following text:

## Ch1 The Sun

## Ch2 Milakovitch cycles

## Ch3 Physical and biogeochimcal climate forcing

Also add a .gitignore file:

$ pico .gitignore

.DS_Store
*.log
log/
logs/

and then save and exit.

If you list all (ls -a) the content of your working directory (the file system in your repo):

$ ls -a

you should see four entries

 .git		.gitignore	Chapters.md	README.md

Both .git and .gitignore are hidden (each start with a dot “.”).

git status

Run a git status command:

On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.gitignore
	Chapters.md
	README.md

nothing added to commit but untracked files present (use "git add" to track)

You have “No commits yet”, and all of the added content is in red (not shown above though) - they have not been staged either.

git stage

stage (add to the tracking system) all of the content in your repo, followed by a status check:

$ git add .
$ git status

On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   .gitignore
	new file:   Chapters.md
	new file:   README.md

The color of the file names is now green (not shown above), git is telling us that files are ready to be commited, or how to go about to unstage.

git commit

When you commit something in git, you lock in the changes, like taking a snapshot. The status of your entire (staged) project will be stored (in the history, or HEAD tree), and you can always go back to this exact content as long as your repo exists. To commit all files and folders that have, at any tine, been staged:

$ git commit -am "initial commit"

[master (root-commit) 51a7ae7] initial commit
 3 files changed, 10 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Chapters.md
 create mode 100644 README.md

The hexadecimal code in the return message (51a7ae7) is the identifier from the commit (or snapshot) history tree. If you want to return to the versions of the included (staged) files in this snapshot you refer to this code. The details for how to do that is covered in the parallel post on Local git control.

git branch

When you created the git repo (with the command git init) the default branch master was created. And all the operations so far has been reated to the master branch. git keeps track of which branch is active at any particular time through a pointer called HEAD in the history tree. HEAD follows the active branch (not the commit) and is called a symbolic pointer. Each branch have its own pointer, that points at the most recent commit for that branch. This means that HEAD indirectly, via the branch pointer, also points at the overall latest commit.

All changes that you do in the working directory tree, like ordinary editing, writing, copying, deleting etc, have no effect on any branch. Neither does staging effect branches. It is only when you commit changes that you attach the staged changes to the active branch.

To list all the branches in your repo:

$ git branch

* master

The branch your are working with is indicate by a *, in our case there is only one branch master.

To create a new branch:

$ git branch b001

If you then again use the basic branch command:

$ git branch

You should now have a second branch.

* master
  new-branch

git log

The git log command return details on your commits and branches:

$ git log

commit 51a7ae7af28bb6264df12fbb7e1df9dc5673326f (HEAD -> master, b001)
Author: Karttur <thomas.gumbricht@karttur.com>
Date:   Thu Feb 20 13:52:25 2020 +0100

    initial commit

The first returned line tells us the full hexadecimal of the latest commit and towards where the HEAD pointer is looking (HEAD -> master, b001). As HEAD points both towards master and b001 we are at the bifurcation point of the branching, but nothing is commited after the branching. You also get information on who did this and when, and the message that went with the commit. The new branch that we added have not yet had any commits and contains nothing.

A more condensed alternative is:

$ git reflog

51a7ae7 (HEAD -> master, b001) HEAD@{0}: commit (initial): initial commit

And then you can add different parameters to the git log command, for instance:

$ git log --all --decorate --oneline --graph

For now this command generates a condensed summary:

* 51a7ae7 (HEAD -> master, b001) initial commit

But it will give a more illustrative picture of the bracnhes once we start working with them.

git checkout and switch branch

In git jargon, a “checkout” switches between different versions of either files, commits or branches - it was used in the post on Local git control to restore deleted files. It can also be used for “checking out” from one branch and “checking in” on another. The Atlassian Bitbucket page on git checkout explains in detail. To switch from the current branch, master in our case, to the b001 branch we just created:

$ git checkout b001

Switched to branch 'b001'

$ git reflog

51a7ae7 (HEAD -> b001, master) HEAD@{0}: checkout: moving from master to b001
51a7ae7 (HEAD -> b001, master) HEAD@{1}: commit (initial): initial commit

The only thing that has actually happened in the repo is that HEAD now points towards the branch b001.

git branch and checkout combined

You can use the checkout command to create a new branch on the fly:

$ git checkout -b b002

Switched to a new branch 'b002'

This will create a third branch, b002, with the same bifucation point from master as b001.

Create new document

While in the branch b002 create a new markdown document:

$ pico ch1-The-Sun.md

and add some notes in it. Save the edits, exit and return to the command line. Check the status:

$ git status

On branch b002
Untracked files:
  (use "git add <file>..." to include in what will be committed)

	ch1-The-Sun.md

nothing added to commit but untracked files present (use "git add" to track)

Temporarily change back to your master branch and try the status command:

$ git checkout master
$ git status

And the message will be the same! It is only when commited that any changes get attached to the active branch.

Return to the branch you were in when editing the file “ch1-The-Sun.md”.

$ git checkout b002

stage and commit to branch

With HEAD pointing towards branch b002, stage and commit the changes:

$ git add .
git commit -m "created ch1-The-Sun.md"

[b002 d6e4774] created ch1-The-Sun.md
 1 file changed, 14 insertions(+)
 create mode 100644 ch1-The-Sun.md

Edit existing document

checkout to change branch to b001:

$ git checkout b001

Switched to branch 'b001'

Open the document Chapters.md and add or edit the text:

$ pico Chapters.md

...
## Add another chapter

Save and exit, and then commit (the document is already staged just add the parameter -a to commit):

$ git commit -am "added chapter in Chapters.md"

[b001 878d2a9] added chapter in Chapters.md
 1 file changed, 2 insertions(+)

Make sure you have a clean working trees and nothing to commit by:

$ git status

On branch b001
nothing to commit, working tree clean

git log

First try:

$ git reflog

which returns an extended summary of the recent events:

878d2a9 (HEAD -> b001) HEAD@{0}: commit: added chapter in Chapters.md
51a7ae7 (master) HEAD@{1}: checkout: moving from b002 to b001
d6e4774 (b002) HEAD@{2}: commit: created ch1-The-Sun.md
51a7ae7 (master) HEAD@{3}: checkout: moving from b001 to b002
51a7ae7 (master) HEAD@{4}: checkout: moving from master to b001
51a7ae7 (master) HEAD@{5}: commit (initial): initial commit

Then try the condensed, graphical alternative introduced above:

$ git log --all --decorate --oneline --graph

* 878d2a9 (HEAD -> b001) added chapter in Chapters.md
| * d6e4774 (b002) created ch1-The-Sun.md
|/  
* 51a7ae7 (master) initial commit

In the response to the last command, you can see that we have three different branches with unique content (from bottom to top):

  • commit-id:51a7ae7; branch: master; message: “initial commit”
  • commit-id:d6e4774; branch: b002; message: “created ch1-The-Sun.md”
  • commit-id:878d2a9; branch: b001; message: “added chapter in Chapters.md”

The HEAD pointer shows that b001 is the singularly active branch.

With b001 as the active branch type:

$ cat Chapters.md

## Ch1 The Sun

## Ch2 Milakovitch cycles

## Ch3 Physical and biogeochimcal climate forcing

## Add another chapter

You can see that the line added (“## Add another chapter”) in the commit related to b001 (878d2a9) is included. If you check out to b002 and run the same command:

$ git checkout b002
$ cat Chapters.md

## Ch1 The Sun

## Ch2 Milakovitch cycles

## Ch3 Physical and biogeochimcal climate forcing

The added line is not there.

git merge

Merging is the git process of joining a bifurcation back into the mainstream. In our example we have three unique branches, a master and the two branch-offs b001 and b002 that bifurcated at the same commit but contain different edits. Both b001 and b002 are “ahead of” master. We need to merge both side branches back into master. The merge command is at the core of git, but also requires some more careful considerations, the Atlassian Bitbucket reference of git merge will probably come in handy.

Fast-Forward merge

A Fast-Forward merge happens when the master pointer still points at the commit that was the bifurcation point of the branch to merge with master. All that is actually needed in such a case is to “fast forward” the master pointer to the pointer of the branch to merge. If you look at the log list above, the HEAD pointer is to b001 and the b001 pointer is towards the commit 878d2a9. Thus if you execute the command $ git merge on these two branches (with master the receiving branch) all that is required is for master to catch up with b001.

Execute git status to ensure that HEAD is pointing to the correct merge-receiving branch (master in our case). If needed, execute git checkout <receiving> command to switch to the receiving branch.

To explore what the differences are between master and b001 and use git diff:

$ git checkout master
$ git diff master..b001

diff --git a/Chapters.md b/Chapters.md
index a80f1ec..01338d4 100644
--- a/Chapters.md
+++ b/Chapters.md
@@ -3,3 +3,5 @@
 ## Ch2 Milakovitch cycles

 ## Ch3 Physical and biogeochimcal climate forcing
+
+## Add another chapter

The response tells us that the line “## Add another chapter” will be added to the file Chapters.md. Execute the merge:

$ git merge b001 -m "merging b0001 to master">

Updating 51a7ae7..878d2a9
Fast-forward (no commit created; -m option ignored)
 Chapters.md | 2 ++
 1 file changed, 2 insertions(+)

The response reports “Fast-forward” and that as a consequence “no commit created; -m option ignored”. Confirm the content of Chapters.md:

$ cat Chapters.md

It should now contain the added line (“## Add another chapter”). Also check the difference betwen master and b001:

$ git diff master..b001

git branch --merged

Before deleting the branch that is now merged with master you can test the command git branch --merged that reports branches that are integrated into master:

$ git branch --merged

  b001
* master

You can now safely delete branch b001:

git branch -d b001

Deleted branch b001 (was 878d2a9).

If you look above (or execute log command), you will see that the commit 878d2a9 is where master is now pointing.

3-way merge

Check the branching of your repo by executing the command:

$ git log --all --decorate --oneline --graph

* 878d2a9 (HEAD -> master) added chapter in Chapters.md
| * d6e4774 (b002) created ch1-The-Sun.md
|/  
* 51a7ae7 initial commit

The result is very similar to before the merging of b001 into master. The only difference is that HEAD now points at master. And that is exactly the result of the Fast Forward merge we just did. But as both remaining branches (master and b002) contain edits compared to the bifurcation point, we can not merge these two using Fast Forward. Instead you have to perform a 3-way merge.

Make sure you are in the master branch:

$ git status

On branch master
nothing to commit, working tree clean

Execute the merge:

$ git merge b002

As you did not give a message (-m) git suggests a default message, either edit or accept it. The merge will complete with a new message:

Merge made by the 'recursive' strategy.
 ch1-The-Sun.md | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 ch1-The-Sun.md

The reported result tell us that “Merge made by the ‘recursive’ strategy.” Check out the graphical representation of what happened:

$ git log --all --decorate --oneline --graph

*   5a76be7 (HEAD -> master) Merge branch 'b002'
|\  
| * d6e4774 (b002) created ch1-The-Sun.md
* | 878d2a9 added chapter in Chapters.md
|/  
* 51a7ae7 initial commit

Check the merge status:

$ git branch --merged

  b001
* master

It is safe to delete branch b002:

git branch -d b001

Merge conflicts

Merge conflicts appear when the same text (or line) in the file has been edited in multiple copies of the same file. In this section you will create a new branch (b003) and make (conflicting) edits to Chapters.md in both master and b003:

$ git checkout -b b003
$ pico Chapters.md

Edit the last chapter title:

## Add another chapter -> ## Ch4 Clouds and water vapor

commit the changes to b003:

$ git commit -am "b003 edits to Chapters.md"

checkout to master and make a different edit to Chapters.md:

$ git checkout master
$ pico Chapters.md

## Add another chapter -> ## Ch4 Sea ice and ocean color

commit the changes to master:

$ git commit -am "master edits to Chapters.md"

Check out the flow of commits for our branches:

$ git log --all --decorate --oneline --graph

* ba31829 (HEAD -> master) master edits to Chapters.md
| * 79d1120 (b003) b003 edits to Chapters.md
|/  
*   5a76be7 Merge branch 'b002'

To merge b003 into master requires a 3-way merge. Make sure you are in the master branch and then start the merge:

$ git merge b003

Auto-merging Chapters.md
CONFLICT (content): Merge conflict in Chapters.md
Automatic merge failed; fix conflicts and then commit the result.

This merge could not be automatically solved, and a conflict is reported. First execture a git status:

$ git status

On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

	both modified:   Chapters.md

no changes added to commit (use "git add" and/or "git commit -a")

git status gives us an escape route, to abort the merge with the command git merge --abort. But git has also, behind the scenes, prepared the working directory version of Chapters.md to highlight the conflicts for you. Thus open the file and inspect the conflicts:

$ pico Chapters.md

## Ch1 The Sun

## Ch2 Milakovitch cycles

## Ch3 Physical and biogeochimcal climate forcing

<<<<<<< HEAD
## Ch4 Sea ice and ocean color
=======
## Ch4 Clouds and water vapor
>>>>>>> b003

The lines above and below the equal signs (“=======”) are where you find conflicts. Above are the edits from the HEAD pointer (pointing to the receiving branch) and below are the edits from the branch to merge. You can edit this file, while also removing the git markers, for example like this:

## Ch1 The Sun

## Ch2 Milakovitch cycles

## Ch3 Physical and biogeochimcal climate forcing

## Ch4 Clouds and water vapor

When you are satisfied, stage the edited file:

$ git add Chapters.md

commit the changes, if you do not give a message (-m) git suggests a default, or you can enter a message interactively:

$ git commit

$ git log --all --decorate --oneline --graph

*   f3a0b75 (HEAD -> master) Merge branch 'b003'
|\  
| * 79d1120 (b003) b003 edits to Chapters.md
* | ba31829 master edits to Chapters.md
|/  
*   5a76be7 Merge branch 'b002'

You can safely delete b003:

git branch -d b003

Resources

Youtube tutorial Introduction to Git - Branching and Merging by David Mahler (20170918)

Atlassian Bitbucket pages on git branches