Setting default commit template in Git

Well-formed commit messages can be rather helpful when tracking the history. Configure a commit template to help you write commit messages in good format and follow it across the whole team.

Write you own commit template file, such as ~/.gitmessage. Below is a good example :

Subject line (try to keep under 50 characters)

Multi-line description of commit to explain
what, why and how this change is being made
(try to limit each line under 72 Characters)

Provide ticket numbers or links to other relevant resource
Example:
[Ticket: #53]

This template structure contains 3 sections:

  1. head, a subject line (followed by a blank line)
  2. body, explains the commit
  3. foot, optional, provides tickets or other information

Setup it as the default commit template with below command:

# Config a custom commit template
$ git config --global commit.template ~/.gitmessage

When you run git commit command, an editor opens containing something like this.

Subject line (try to keep under 50 characters)

Multi-line description of commit to explain
what, why and how this change is being made
(try to limit each line under 72 Characters)

Provide links or ids to relevant issues or other resources
Example:
[Ticket: #53]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   my-plugin.php
#

Then replace the 3 parts with your actual content.

Branches management in Git

Create a new branch

# Create a new branch named develop
$ git branch develop

You can also download a new branch from remote.

Switch to a branch

# Switch to develop branch
$ git checkout develop

-b option allows you to create a new branch and switch to it in one command:

# Create develop branch and switch to it.
$ git checkout -b develop

To checkout to a remote branch, run:

# Checkout to origin/master 
$ git checkout origin/master

Note: After switched to a remote branch, you would be in a detached state which means the branch won’t move after you made a new commit here. The reason is that you can not modify a remote branch, it is read-only for you.

List branches

# List branches
$ git branch
* develop
  master

* indicates the branch that you are currently on.

To see the branches and their last commit, add -v option:

# List branches and their last commit message
$ git branch -v
* develop 625cdcb initial commit
  master  b1f092d feat: add settings

To see the branches that have been merged or unmerged into the current branch, use --merged option:

# List only the branches that have been merged to the current branch
$ git branch --merged.

The branches that have been merged can be deleted safely, since their commits have been contained in the current branch.

To see the branches that have not been merged to the current branch, use --no-merged option:

# List only the branches that have not been merged to the current branch
$ git branch --no-merged

Rename a branch

# Rename old-branch to new-branch
# -m or --move, rename a branch
$ git branch -m old-branch new-branch

Delete a branch

# Delete test branch
$ git branch -d test

# Force to delete a branch if it has not been merged yet.
$ git branch -D test

Note: you can not delete the branch you are currently on, first switch to another branch.

See more : how to delete a local and a remote branch.

Stashing changes in Git

stash command takes changes in working tree and staging area away and store them on a stack. You can reapply the changes later.

Stash changes

# Stashes changes in working tree and staging area away 
$ git stash

# Stash changes in working tree and index, and keep staged changes in index
$ git stash --keep-index

# Stash changes, also include untracked files
$ git stash --include-untracked

# Stash changes, also include untracked and ignored files
$ git stash --all

To stash only changes in specified files or folder, run below command:

# Stash only changes in pathspec
$ git stash -- <pathspec>

# Examples:
# Stash only changes in inc/menu.php
$ git stash -- inc/menu.php

List all stashes

# List the stashes that have been made on the curren branch 
$ git stash list
stash@{0}: WIP on master: b1f092d update: hello.php

The above result shows the stash name, the branch name, and the commit this stash was based on.

Reapply stashed changes

# Apply the top stash on the stack
$ git stash apply

Use stash@{n} to reference the n stash from the top on the stack, it is started from 0 :

# Apply the top stash on the stack
$ git stash apply stash@{0}

# Apply the stash before stash@{0} on the stack
$ git stash apply stash@{1}

Be aware that the staged changes in the stash are not restaged. To do that, run:

# Revert working tree and staging area
$ git stash apply --index

The reapplied stash is not removed from the stack. To remove a stash, use drop command:

# Remove the top stash on the stack
$ git stash drop stash@{0}

To reapply a stash and remove it from stack in one command, use pop command:

# Repplay a stash and remove it from stack
$ git stash pop stash@{0}

Note:

You do not have to be on the same branch to apply the changes. There will be merge conflicts if there is change can not be applied cleanly.

Show content of a stash

# Show content of the top stash
$ git stash show stash@{0}

# Show cnotent of the second recent stash in patch form
$ git stash show -p stash@{1}

Clear all stashes

# Remove all stashes in the stack
$ git stash clear

Note: The stashes removed may be impossible to recover.

Setting up a local branch to track a remote branch in Git

Set up upstream branch for a branch

To set up a local branch to track a remote branch, use :

# Suppose you are on local temp branch
# Set up current branch temp to track topic branch from origin.
$ git branch -u origin/test

Now origin/topic is the current branch’s upstream branch, you can use @{u} to reference it for shortcut instead of origin/topic.

# Merge from upstream branch, 
# here it is origin/topic if you are on local temp branch.
$ git merge @{u}

Check which remote branch a local branch is tracking

If you want to see which remote branch a local branch is tracking, run below command:

# List local branches and which remote branches they are tracking.
$ git branch -vv
develop 99914fb [origin/develop: ahead 2] fix: missing comma
master 04a4f6a [origin/master: ahead 1, behind 2] feat: add menu
* temp 94f4439 [origin/topic: ahead 2] feat: add custom post type
test ac5446a [origin/test] initial commit

This command also tells whether a local branch is ahead or behind its upstream branch.

Viewing commit history in Git

git log command shows the commit logs. It provides many useful options to help you view and find the commit history.

Show commit history in default format

# Show the whole commit history
$ git log
commit 69c0b0bd7ff8cba857cae89a01c9da4a27b43632
Author: xxx <xxx@xxx.com>
Date:   Sun Dec 9 21:30:11 2018 +0800

    feat: add main php file

commit 9438770e0d9ba6d775a61d9b4d1d4030a7ee682b
Author: xxx <xxx@xxx.com>
Date:   Sun Dec 9 19:34:45 2018 +0800

    Initial commit

Show commit history in short format with one log in one line

$ git log --oneline
69c0b0b feat: add main php file
9438770 Initial commit

Show commits containing specified string

# Show only commits whose commit messages contain 'main menu'
$ git log --grep 'main menu'

Show commit history with limited number

# Show only the last two commit logs
$ git log -2

Show commit history of limited time period

# Show commit logs that are made in the last 2 weeks
# --after or --since works the same
$ git log --after=2.week

# Show commit logs that are made after 2018-12-01
$ git log --after=2018-12-01

# Show commit logs that are made before 2018-12-01
$ git log --before=2018-12-01

Show commits related to a string

# Show only those commits that changed the number of occurrences of update_post_meta,
# means the commits add or remove 'update_post_meta'
$ git log -S update_post_meta

Show commits that changed a file / files

# show commits that introduced changes to my-plugin.php
$ git log -- my-plugin.php

# show commits that introduced changes to files in inc/ directory
$ git log -- inc/

Show commit history with difference/changes

# Show commit logs with differemce introduced in each commit
$ git log -p 

Show commits of specified author or committer

# Show only commits made by john
$ git log --author john

# Show only commits committed by john
$ git log --committer john

Show commits in graph displaying the commit structure

# Show all commits of branches in a graph structure
# --all,
# --graph,
# --oneline,
# --decorate, 
$ git log --all --graph --oneline --decorate