I have been studying Git and here is what I learned.

Using a Git workflow

This tutorial about the Git branching model is awesome. Read here

I am following this simple version for branches:

  • Master
  • Develop
  • hotfixes

I start in master.

Create a branch develop to build everything.

When the tests pass or at least most of them, then switch to master and merge develop.

Create a hotfix branch to resolve tests that didn’t pass or things I broke. After merging them to master and develop. The hotfix branches are deleted.

Using a CHANGELOG to bump the versions merging develop to master and hotfix to master.

I follow the “keep a changelog” tutorial here and a light semantic version from the Semver website here. Using the Major.Minor.Patch syntax.

I use Sublime or vim for scripts or small projects. Lately I use IntelliJ Ultimate which I find amusing with the auto completion, shortcuts, and the git diff tool to see changes.

The Pro Git is a great resource to learn Git in more detail.

Working with master and develop

Initialize the repo with git init or clone the repo.

Create the CHANGELOG file with touch CHANGELOG.md.

Create the develop branch git branch develop.

Work on the develop branch.

Commit in small increments

(develop)$ git commit -am "Short summary of change"

Switch to master and merge

(master)$ git checkout master
(master)$ git merge develop -m "Short summary of merge"

Update CHANGELOG file with next version <version number>. Then commit:

(master)$ git commit CHANGELOG.md -m "Bumped version to <version number>"

Create an annotated tag for the <version number>.

(master)$ git tag -a <version number>

Push changes to remote if needed:

(master)$ git push origin master

Creating hotfixes of failed tests or things I messed up

Create a branch from master increasing the patch version number of Major.Minor.Patch. If the current version is 1.2 then:

(master)$ git checkout -b hotfix-1.2.1 master

Update the CHANGELOG to increase the version then commit.

(hotfix-1.2.1)$ git commit CHANGELOG.md -m "Bumped version number to 1.2.1"

Make the changes and commits in small increments.

Then merge with master and tag

(master)$ git checkout master
(master)$ git merge --no-ff hotfix-1.2.1
(master)$ git tag -a 1.2.1

Also merge with develop

(master)$ git checkout develop
(develop)$ git merge --no-ff hotfix-1.2.1

Then delete the branch

(develop)$ git branch -d hotfix-1.2.1

Other Git/Github tutorials I wrote:

My take on the Git cheat sheet

  • Using short status: git status -s
  • Setup .gitignore
  • Use git diff to see staged/unstaged changes or use an IDE
  • Removing files from Git git rm <filename>
  • Rename files git mv <filename>
  • View the commit history git log
  • Last commit git log -1
  • Ammend the last commit to change the comment git commit --amend
  • Log in one-liner git log --pretty=oneline
  • Show the last 4 commits git log --pretty=oneline -4
  • View the URLs of the remote git remote -v
  • Fetch data from origin git fetch origin
  • Merge remote with local branch git pull
  • In git push origin master the word origin is just a shortname for the remote. You can rename to homersimpson if you want.
  • Show more info about a remote git remote show origin
  • Rename a remote git remote rename origin to homersimpson
  • Check the remote again git remote -v shows homersimpson https://somerepo
  • Show the number of tags git tag | wc -l
  • With git tag show all the tags
  • Show only those that start with v2: git tag -l "v2.2*"
  • Show the details of a tag git show <version number>
  • Create a lightweight tag: git tag <version number>
  • Create an annotated tag: git tag -a <version number>
  • Create a shortcut alias like this: git config --global alias.last5 'log --pretty=oneline -5'
  • Then run git last5 to get the same output
  • Create a branch git branch newBranch
  • Switch to that branch git checkout newBranch
  • Create a branch and switch to it in one command git checkout -b anotherBranch
  • List local branches $ git branch
  • History of commits git log --all --decorate --oneline --graph
  • Last commit in each branch git branch -v

Add Git branch to the command prompt

Edit .bashrc as seen on stackoverflow here:

# Git branch name
parse_git_branch() {
        git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'

Add this to .bashrc after the above function. The enclosed \e[0;31m ....\e[m will set the command prompt to red.

PS1="\e[0;31m\h\$(parse_git_branch)\$ \e[m"

Merging conflicts

When doing git merge, the output might say CONFLICT: Merge conflict in <filename here>

Open the conflict file manually and correct the conflict.

If the file shows something like this:

<<<<<< HEAD changes2.md
Updated changes2
Finished feature2
>>>>>>> feature2:changes2.md

Then the master branch has the content Updated changes2 and the feature2 branch has Finished feature2. Remove any Git notes and leave the correct changes such as:

Updated changes2
Finished feature2

Then commit the conflict:

(master)$ git add changes2.md
(master)$ git commit -m "Merge conflict fixed for feature2"

More about merge tools:

  • Use an IDE
  • Using git mergetool or advanced merging in the Git book here
  • Find tools available git mergetool --tool-help
  • Using vimdiff tutorial here

Git rebase

More about rebase here

See everything done in git with git reflog

Use git reflog as seen on the Dangit Git tutorial here

(master)$ git reflog
aaaf830 (HEAD -> master) [email protected]{0}: commit (merge): Merged conflict for cities
32a6bb7 [email protected]{1}: checkout: moving from newBranch to master
37f3122 (newBranch) [email protected]{2}: commit: Added New Orleans to Cities
5cb15fc [email protected]{3}: checkout: moving from master to newBranch
32a6bb7 [email protected]{4}: commit: Added Houston to Cities
f4b7070 [email protected]{5}: commit (merge): Merge conflic fixed
3c897b2 [email protected]{6}: checkout: moving from newBranch to master
e567c27 [email protected]{26}: commit: Deleted names.txt
a715798 [email protected]{27}: commit: Added a city to cities
a1b0314 [email protected]{28}: commit (initial): Created files names and cities

Go back in time to a previous commit with this syntax:

$ git reset [email protected]{index}

Committed to the wrong branch

Commited to the wrong branch master:

(master) $ echo "England" >> countries.csv
(master) $ git commit -am "Added England to Countries"

Check the log:

(master) $ git last5

4c769 (HEAD -> master) Added England to Countries
aaaf8 Merged conflict for cities
37f31 (newBranch) Added New Orleans to Cities
32a6b Added Houston to Cities
f4b70 Merge conflic fixed

Use git reset HEAD~ --soft to remove the last commit from master but keep the changes in the working directory.

(master) $ git reset HEAD~ --soft

(master)$ git last5
aaaf8 (HEAD -> master) Merged conflict for cities
37f31 (newBranch) Added New Orleans to Cities
32a6b Added Houston to Cities
f4b70 Merge conflic fixed
5cb15 Added Rome to Cities

(master)$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   countries.csv

Use git stash to save the state of the working directory and index. More about git stash in the official docs here.

(master) $ git stash

Saved working directory and index state WIP on master: aaaf830 Merged conflict for cities

(master)$ git status
On branch master
nothing to commit, working tree clean

Switch branches and use git stash pop to remove the last state from the stash list and apply it to the current branch.

(master) $ git checkout -b addEngland
Switched to a new branch 'addEngland'

(addEngland) $ git stash pop
On branch addEngland
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   countries.csv

(addEngland)$ cat countries.csv 

(addEngland)$ git commit -am "Added England to Countries"
[addEngland 99f82cb] Added England to Countries
 1 file changed, 1 insertion(+)

Check the log in the branch:

(addEngland)$ git last5
99f82 (HEAD -> addEngland) Added England to Countries
aaaf8 (master) Merged conflict for cities
37f31 (newBranch) Added New Orleans to Cities
32a6b Added Houston to Cities
f4b70 Merge conflic fixed

Go to master branch

(addEngland)$ git checkout master
Switched to branch 'master'

(master)$ git last5
aaaf8 (HEAD -> master) Merged conflict for cities
37f31 (newBranch) Added New Orleans to Cities
32a6b Added Houston to Cities
f4b70 Merge conflic fixed
5cb15 Added Rome to Cities

Ask me anything on Linkedin