Checking local branch is ahead or behind remote branch

To see a local branch is ahead or behind its upstream branch, use:

# List all branches with more information:
# id, message and relationship with their upstream branches
$ 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 feat: add custom post type
test ac5446a [origin/test] initial commit

Above information illustrates the following relationship with remote ones:

  • develop branch is ahead origin/develop by 2 commits
  • master branch is ahead by 1 commit, and behind by 2 commit
  • temp branch is not tracking any remote branch
  • test branch stays up to date

Note that the remote information may not be up to date, it just present situations the last time you communicated with remote server.

To see up to date information, you can first update changes from remote :

# Fetch update from all remote tracking branches. Note it does not
# merge them to the local branches.
$ git fetch --all
$ git branch -vv

Stopping tracking a file in Git

This article shows you how to stop tracking a file/folder that has been tracked before.

To untrack a file that has been committed, what you do is adding a new ignoring rule and removing the file in a commit.

Below is a full example of ignoring /assets/my-style.css .

Step 1: add below content to .gitignore file to add an ignore rule.


Note: See ignoring files for how to create your  .gitignore file and write ignore rules.

Step 2: remove it from repository and commit the changes .

# Stage .gitignore
$ git add .gitignore

# Remove my-style.css file from staging area, my-style.css
# in working directory is left alone.
# --cached, only apply to staging area
$ git rm --cached -- assets/css/my-style.css

# Commit them
$ git commit

Thus, my-style.css will not be tracked any more. Be aware that it still remains in previous history.

To stop tracking a directory is similar, just replace above file with a folder in .gitignore file and git rm command.

Ignoring files in Git

Ignore files in a git repository

Use .gitignore to allow sharing ignoring rules (version controlled)

If you want some files being untracked in a repository, create an .gitignore file at its root directory and commit it. .gitignore file is used to list all the file patterns to ignore, standard glob patterns work in it.

Basic rules for patterns have been included in below example .gitignore file :

# ignore all .class files

# exclude lib.class from '*.o', meaning all lib.class are still tracked

# ignore all json files whose name begin with 'temp-'

# only ignore the build.log file in current directory, not those in its subdirectories

# specify a folder with slash in the end
# ignore all files in any directory named temp

# ignore doc/notes.txt, but not doc/server/arch.txt

# ignore all .pdf files in the doc/ directory and any of its subdirectories
# /** matches 0 or more directories

Remember to commit it:

$ git add .gitignore
$ git commit 

Note: Adding new patterns in .gitignore won’t affect the files already tracked by Git. You can stop tracking a file.

You can have more than one .gitignore file in subdirectories. Its content will only apply to the folder it resides.

Use .git/info/exclude to only ignore files locally (not version controlled)

If you just want a personal and local ignoring configuration without committing a .gitignore file, use .git/info/exclude to achieve that.

What you do is just adding exclude rules in .git/info/exclude within in the root of a repository.

Any rule added in the file will not be pushed to a remote repository. This way enables you to ignore locally generated files and no need to worry about other users.

Ignore files in all repositories

If you want to ignore some files for all repositories, you can set a global gitignore file. Below is an example to ignore .DS_Store files :

File ~/.gitignore_global :


Then configure it as your global gitignore settings in Git :

$ git config --global core.excludesfile ~/.gitignore_global

Debug gitignore files

check-ignore command can be used to debug if a file/folder is excluded by some ignoring/exclude rules you’ve set up :

$ git check-ignore -v <pathname>

If the pathname matches an exclude pattern, it outputs the gitignore file, line number, pattern and your query pathname. Otherwise, nothing is output.

Note: By default, tracked files are not output since they are not subject to exclude rules. If a file is tracked before and untracked currently, it can be output.

Below example to debug if user.csv is excluded:

# Debug whether user.csv is exclude by some ignoring rule 
$ git check-ignore -v users.csv
.gitignore:3:*.csv      user.csv

Here user.csv is excluded by *.csv pattern in .gitignore.

Read more:

Undoing merge or pull in Git

Undo pull and recover to previous HEAD commit

If you want to undo git pull action which has been executed and go back to the previous state, use :

# Undo pull action
# --hard, not only reset the current branch and staging area, but also working directory
# ORIG_HEAD, the old HEAD, here it is the HEAD before pull action
$ git reset --hard ORIG_HEAD

Undo pull but keep unstaged changes in working directory

Note the command above will discard changes you have made in working directory. If you have not staged them and want to keep, use --merge option instead :

# Undo pull action but keep unstaged changes in working directory
$ git reset --merge ORIG_HEAD  

Discarding changes in working directory in Git

To discard changes in working tree to make it clean, a safer way is to use stash command. stash takes the changes in working directory away and you can get them back later.

# Stash changes in working directory
$ git stash

# Apply the latest stashed changes
$ git stash apply

Read stashing changes for more about how to use stash.

If you still want to discard the changes directly, use below command (Changes can not be recovered):

# Discard the changes in working directory and staging area.
# Be aware that changes can not be recovered.
$ git reset --hard

Deleting a local or remote branch in Git

Delete a local or remote branch in Git. Last updated: 2018-12-22

Delete a local branch

Make sure you are not on the branch to be deleted :

# Delete local branch 'test'

# First switch to another branch if you are on 'test' branch
$ git checkout master

# Do delete action
$ git branch -d test

If your branch has not been merged, use -D option to force delete it :

$ git branch -d test
error: The branch 'testing' is not fully merged.
If you are sure you want to delete it, run 'git branch -D test'.

$ git branch -D test
Deleted branch test (was 4f10b4a).

Delete a remote branch

Use --delete option to push command :

# Delete a remote branch 'test' on Git version above v1.7.0
$ git push origin --delete test

The command above is available after Git v1.7.0. If you are using an earlier version :

# Push empty source to remote branch of 'test', meaning deleting it
$ git push origin :test

Finding a file in Git

Find a file in working directory

# Find 'a.c' in the current directory and its subdirectories.
$ git ls-files -- '**/a.c' a.c

Find a file in staging area

# Find 'a.c' in the current directory of staging area
# --cached, show files in the staging area
$ git ls-files --cached -- '**/a.c' a.c

Find a file in a commit

It also shows whether a file is tracked or not in a commit.

# Find 'a.c' in the current directory of HEAD commit
# -r, recursely
# --name-only, list file names (including path) only
$ git ls-tree -r --name-only HEAD | grep a.c

Command git ls-tree -r --name-only <commit> lists all files in a specific commit.

Getting count of tracked files in Git

Get count of tracked files in Git. Last updated: 2018-12-20

Get count of tracked files:

# Get count of tracked files in the current directory, including files in its subdirectories
$ git ls-files | wc -l

To get count of all tracked files in the repository, remember navigate to the root directory of repository.


git ls-files lists all tracked files in the current folder:

# List tracked files
$ git ls-files


wc means word count, it can be used to count bytes, words, or lines. -l option indicates to count lines.

Creating a tag for a commit in Git

Create a tag for a commit in Git. Last updated: 2018-12-19

Create a tag for a commit :

# Create a tag "v1.0" for HEAD.
$ git tag v1.0

# Create an annotated tag for HEAD with "-a" option.
# -a, this is an annotated tag which can include other information in an object, 
#     such as message, name, email
$ git tag -a v1.0 -m "Formal version v1.0"

# Create a tag for commit "06d49a9"
$ git tag v1.0 06d49a9

Note: By default, git push does not push tags to the remote repository, you need to explicitly push them:

# Push a tag "v1.0" to remote repository
$ git push v1.0

# Push all tags to remote repository
$ git push --tags

Setting up Beyond Compare as difftool and mergetool in Git

Set up Becond Compare as difftool and mergetool in Git. Last updated: 2018-12-18

Environment: Windows, Git v2.13.2

You can use git commands or directly edit global git config file to configure Beyond Compare as difftool and mergetool.

Method 1 : use git commands

# Config Beyond Compare 4 as difftool

$ git config --global diff.tool bc4
$ git config --global difftool.prompt false
# Note: set parameters for Beyond Compare tool
$ git config --global difftool.bc4.cmd '"C:\Program Files\Beyond Compare 4\BCompare.exe" "$LOCAL" "$REMOTE"' 

# Config Becond Compare 4 as mergetool

$ git config --global merge.tool = bc4
$ git config --global mergetool.prompt false
$ git config --global mergetool.bc4.path 'C:\Program Files\Beyond Compare 4\BCompare.exe'

Method 2 : directly edit global git config file

Edit git global git file .gitconfig in your home directory and add below contents:

    tool = bc4
    prompt = false
[difftool "bc4"]
    cmd = "\"C:\\Program Files\\Beyond Compare 4\\BCompare.exe\" \"$LOCAL\" \"$REMOTE\""
    tool = bc4
    prompt = false
[mergetool "bc4"]
    path = C:\\Program Files\\Beyond Compare 4\\BCompare.exe