Git, usually you have multiple remote git repos and multiple local git repos (on different machines). For local repos, there are three phases for the local files: working directory, staging area, and git directory (repo).

In the working directory, files could be untracked, unstaged, or deleted. Once the file is staged, it’s in the staging area. The staged files are those ready to be commited to the local repo.

Configuration

git config

/etc/gitconfig every user on the system ~ git config –system

~/.gitconfig or ~/.config/git/config specific to your user ~ git config –global

.git/config the current repository ~ git config

Each level overrides values in the previous level.

identity

1
2
git config --global user.name "XXX"
git config --global user.email XXX@email.org

default editor

1
git config --global core.editor emacs

check settings

1
git config --list

set aliases

1
2
3
4
5
6
7
8
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global pull.rebase true # make --rebase the default in git pull
git config --global credential.helper cache

Initialization

git init

1
2
3
git init <dir> # initialize empty repository in <dir>
git init # initialize a repository in an existing directory
git init --bare --shared # initialize an empty remote repository (no working directory) and give the group write permissions to this repository properly

git clone

1
2
3
4
git clone <url> [<dir>] # clone a repository in <dir> from <url>
git clone --bare <proj> <proj.git> # clone the <proj> repository to create a new bare repository
git clone <bundle> <repo> # unbundle
git clone --recursive <url> # automatically initialize and update each submodule

How to retrieve all remote branches: Once you git clone a remote repo, it will sync the master branch by default. To see how to retrieve all remote branches, click here

Saving changes (staging and committing)

git add

1
2
3
4
git add <file>|<dir> # track and stage new file or whole directory
git add -i # interactive staging
git add -p # interactively partial staging
git add -A # add every file

git commit

1
2
git commit -m <message> # commit the staged snapshot with <message>
git commit -am <message> # commit all changes of the staged area, with those deleted files

Ignoring new files or Removing files

git rm

1
2
git rm --cached [-r] <file> # stage the removal of <file>, but leave the file in the working tree
git rm [-r] <file> # stage the removal of <file>

Inspecting

git status

1
git status # list status of files that are staged, unstaged, and untracked.

git status works on working directory and staging area.

git log

1
2
3
4
5
6
7
8
9
git log # display entire commit history, press `space` to scroll, and press `q` to exit.
git log -n <limit> # display limited number of history
git log --oneline # display condensed history
git log --stat # display commit history with simple status
git log -p # display commmit history with very detailed status
git log --author=<pattern> # commits by a particular author
git log --grep=<pattern> # search commits by <pattern>
git log <since>..<until> # commit history between revision references
git log <file> # commit history on a particular file

special syntax

.. syntax: compare between branches

~ syntax: make relative reference, i.e. HEAD~1 refers to the parent of current commit

git diff

1
2
3
4
git diff HEAD # HEAD points to the most recent commit
git diff --staged # see the difference of just staged
git diff <b1>..<b2> -- path # see difference of path between <b1> and <b2>, that are revision references, default is current branch
git diff --name-status ... # show condensed info

Actually, with urxvt and zsh, <Tab> helps a lot.

Checkout

1
2
3
git checkout <branch> # recover <branch>
git checkout <commit> # recover <commit>
git checkout [[<branch>|<commit>] --] <file> # recover particular file

Undoing

git checkout

syntax same as above

git revert

1
git revert <commit> # generate a new commit that undoes all the changes introduced in <commit>, then apply it to current branch

git revert doesn’t change the project history, it’s safe for commits that have been pushed to a shared repository. git revert is able to target an individual commit at an arbitrary point in the history.

git reset

1
2
3
4
5
git reset <file> # move <file> from staged area back to the working directory
git reset [--mixed] # reset the staged area as the most recent commit, --mixed flag is default
git reset --hard # reset the staged area and working directory as the most recent commit
git reset --soft # the staged area and working directory are not altered
git reset [--hard] <commit> # reset the staged area [and working directory] as the snapshot of <commit>

git reset <commit> will abort commits after .

ACTUALLY git revert and git reset both do not affect the untracked files, both are like an operation of moving pointer between snapshots.

git clean

1
2
3
4
5
6
git clean # remove untracked files from working directory
git clean -n # dry run of git clean
git clean -f # with force flag
git clean -f <path> # remove untracked files in specific <path>
git clean -df # remove untracked files and directories in current directory
git clean -xf # remove untracked files and ignored files

History manipulating

git commit

1
git commit --amand [--no-edit] # combine the staged area change with the previous commit and replace the previous commit, --no-edit flag for not changing the commit message.

A very convenient way to fix up the most recent commit. Better to avoid amending public commit.

git rebase

1
2
git rebase <base> # rebase the current branch onto <base>, which is a revision reference
git rebase -i <base> # interactive one, pick and squash

The primary reason for rebasing is to maintain a linear project history.

In addition, rebasing is useful for changing the git history, see notes on git part 2.

git reflog

1
2
git reflog # show the reflog of the local repo
git reflog --relative-date # show the relative date information

Synchronization

git remote

1
2
3
4
git remote [-v] # list the remote repos, -v flag for displaying remote repo address
git remote add <name> <url> # create a new remote connection
git remote rm <name> # remove remote connection to <name>
git remote rename <oldName> <newName> # rename the remote repo

git clone will create the remote repo as origin.

git fetch

1
2
git fetch <remote> # fetch all the branches from <remote>
git fetch <remote> <branch> # fetch specific <branch> from <remote>

Fetched content is represented as a remote branch, no effect on local working.

1
git branch -r # view remote branches

git pull

1
2
git pull <remote> # fetch the <remote>'s copy of current branch and merge it into local copy
git pull --rebase <remote> # use rebase

syncBranches

Following codes show how to create local branches for all remote tracking branches:

1
2
3
4
5
# sol 1
for b in `git branch -r | grep -v -- '->'`; do git branch --track ${b##origin/} $b; done

# sol 2, ?, not tested yet, seems more robust?
git branch -r | grep -v -- ' -> ' | while read remote; do git branch --track "${remote#origin/}" "$remote" 2>&1 | grep -v ' already exists'; done

git stash

1
2
3
4
5
6
git stash # temporary save uncommited stuff
git stash list # get a list of all stashes
git stash apply [<stash>] # restore [a specific <stash>] stashed stuff
git stash pop [<stash>] # apply and remove the most[|a specific <stash>] recent stashed stuff
git stash drop [<stash>] # remove a stash from the stash list
git stash show [-p] [<stash>] # show the changes recorded in the stash as a diff between the stashed state and its original parent. -p for enabling the patch mode.

By default, git stash will only stash those indexed files, which means you need to git add untracked files first to make them into staged area, then stash them.

Since version 1.7.7, you could use following flag to include stashing untracked files:

1
git stash -u

git push

1
2
3
git push <remote> <branch> # push specific <branch> to <remote>
git push <remote> --all # push all the local branches to <remote>
git push <remote> --tags # --tags flag sends local tags to <remote>

Branch

git branch

1
2
3
4
5
6
7
git branch # list all branches
git branch <branch> # create a <branch> branch
git branch -d <branch> # delete <branch>, it prevents deleting the branch that has unmerged changes
git branch -D <branch> # force delete <branch>
git branch -m <branch> # rename current branch to <branch>

git checkout -b <newBranch> [<oneBranch>] # create and checkout <newBranch>, based on current branch or <oneBranch>

git merge

1
2
git merge <branch> # merge <branch> into current branch
git merge --no-ff <branch> # always generate a merge commit

fast-forward merge occurs when there is linear from current branch to target branch.

3-way merge is of two branch tips and their common ancestor. It may encounter conflicts.

git rebase

Also, git rebase can be used for merging branches. Syntax see above

git help

1
git help <verb>