In my day to day job I use Git very frequently, but I’ve never spent the time to properly get my head round the more complex parts, instead relying on muscle memory and StackOverflow for those occasions that I get stuck.
I decided to read parts of Pro Git (git-scm.com/book/en/v2), going back to basics to learn a bit more about the internals and more advanced features of Git, and to solidify my understanding of this powerful but at times opaque tool.
Useful aliases can be found at the bottom of this page
git config --global --edit
to edit the global Git config file, --system
for the system config (/etc/gitconfig), --local
for the repository local file (which is the default config file Git will read from - stored in .git/config
in a repository)
git config --list --show-origin
to see the full list of config parameters and their originsgit config --global core.editor vim
to set the editor for commit messages and stuffgit status
command is used to see the state of files in your repository
git status -s
for a shorthand easier to parse status
git add <file>
to add files to the staging area (duh). Specifying a directory will add all the files in that directory/
to avoid recursivity (patterns are recursive by default) (basically specifying the project root) - ending with /
specifies a directory!
, e.g. if you ignore *.a
but you want lib.a
you’d use !lib.a
**
to match nested directories, e.g. a/**/z
matches a/b/z
, a/b/c/z
etc.git diff
with no args shows files changed but not stagedgit diff --staged
shows staged files (--cached
is a synonym)git commit -a
skips the need to git add .
git rm
is used to remove a file from the staging area, and will also remove it from the working directorygit rm --cached
(or --staged
) removes a file from the staging area without removing it from the working directory
git rm
commands but must make sure to include a \
before a *
to disable shell filename expansiongit log
git log
is used to view the commit history in reverse chronological order
-p
to show the difference (patch output) in each commit-n
for a number n
to show the last n
commits--pretty
is used to change the log output, e.g. --pretty=oneline
prints single line logs with the hash and commit message. A custom format can also be created with --pretty=format:
(see man page for more)--graph
shows the branch and merge history--author
and --grep
to filter for specific authors and for specific keywords in commit messages respectively-S
(pickaxe) takes a string and shows only commits that changed the number of occurrences of that string (e.g. adding or removing references to method calls)--no-merges
to hide merge commits--
to separate from other options. In fact it is the default last argumentgit commit --amend
(without changes staged it will just allow changing the commit message)git reset HEAD <file>
git checkout -- <file>
, Git will replace your working directory version with the last staged or committed versiongit restore
is an alternative to git reset
git restore --staged <file>
git restore <file>
(rather than checking out the file)git remote -v
shows the remotes you have configured for the repository. origin
is the default name Git gives the server you cloned from, but remotes can have different names if desired.
git remote add <shortname> <url>
git fetch <remote>
, e.g. git fetch origin
origin
’s main branch is then accessible locally as origin/main
git fetch <remote>
git pull
can be used to fetch and merge a remote branch into your current local branch, if you have your current branch set up to track a remote branch
git clone
sets up the local main
branch to track the remote main
branchpull
is a fetch
and merge
operation in onegit push <remote> <branch>
- git clone
again sets up the origin
remote and main
branch automaticallygit remote show <remote shortname>
is good for seeing the configuration for a specified remote
git tag
to list tags, -l "v1.8.*"
to find specific tags with a wildcard (requires -l
)git tag -a v1.4 -m "This is v1.4"
to create a new annotated tag with a messagegit show v1.4
to show the information about a taggit tag v1.4
without -a
creates a lightweight tag - lightweight tags can be thought of as just a commit hash stored in a file, no more information is keptgit tag -a v1.4 <commit hash>
- can be a partial commit hash as long as it’s uniquegit push origin v1.4
, similar to pushing to a remote branch
git push origin --tags
to push all local tagsgit push origin --delete <tagname>
git checkout <tagname>
to checkout a tag, this puts you in a detached HEAD state
git checkout -b <branchname> <tag>
git branch <branch>
creates a new branch, git checkout <branch>
switches you to that branch (changes HEAD to the new branch pointer)
checkout
and the files will be restored to the state they were in at that the point of branchinggit log --oneline --decorate --graph --all
will print the history of commits, showing branches and history divergenceVarious useful aliases
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'