Classifying Git actions
Here is a slowly growing summary of Git commands I find helpful, addressed the dear reader. Again, I appreciate anyone to correct my misunderstandings, if any.
Git is a gigantic beast, and I try to group various actions by their point of departure and arrival. Indeed, Git actions occur between the working tree, the local, and remote repo. Commands add
, commit
, and push
, among others, transfer data from the local end to the remote end. Commands clone
, fetch
, pull
, and reset
, among others, transfer data from the remote end to the local end.
By convention, commands meant to be run in a Bash shell is prefixed with a $
, and terms enclosed in <>
aren’t verbatim. Remember that Git commands accept the working directory to be either the top directory (which we assume) or any of its subdirectory, except .git/
, the local repo itself.
For more information, Git man pages can be called by:
$ git help <command>
Or equivalently:
$ git <command> --help
From the tree to the local: add
Action of adding stages changes in the working tree to the stash. To add everything—new, modified, and deleted files:
$ git add .
To see a summary of staged changes:
$ git status
To show changes in the working tree not added:
$ git diff
To compare the indexed files with the latest commit:
$ git diff --staged
Instead, to compare a specific file in the working tree with the committed version of it:
$ git diff <commit> <certain_file>
There will be a new page that summarizes the modification. Navigation commands are identical to less
, and similar to Vim. Hit j
or e
to forward one line, and k
or y
to backward one line. Hit f
to forward one window, and b
to backward one window. Hit d
to forward one-half window, and u
to backward one-half window. Finally, hit q
to quit.
From the tree to the local: commit
To commit your present files from the stash to the local repo, with a commit message:
$ git commit -m "<commit message>"
A commit message should summarize the new work concisely, within 70 characters. If you can’t, you should probably split your work into more than one commits. To save space, it is conventional to use verbs in its base form, without period in the end.
You may modify your commit message even after you commit, with:
$ git commit --amend
An editor should open, showing the commit message and the status. This file is saved as .git/COMMIT_EDITMSG
. I find it useful to edit the commit message this way, because I don’t have to backslash-escape special characters. You may also add more explanatory lines below, separated from the commit message with a blank line.
But what if you want to cancel the last 3 commits, in order to make a new commit from the present tree? You can revert the head, and commit as usual.
$ git reset HEAD~3
Sometimes we add a tag to single out more significant commits, especially when a commit is released to the public. A tag can be added when you have modified the working tree. To add a tag to the latest commit:
$ git tag -a <tag_number>
To simply list all tags:
$ git tag
To push tags to the remote, you have to do:
$ git push --tags origin
The commit log lists commit hashes, authors, time stamps, and commit messages. To view the commit log:
$ git log
To make the log concise and informative:
$ git log --all --decorate --oneline --graph
Pointer HEAD
refers to the current commit. To retrieve its ancestors, two operators could be used. Pointer HEAD~2
refers to the eldest parent of the parent of the head. Pointer HEAD^3
means its third-to-last eldest parent of the head, and so on. The two operators may be composed, for instance as HEAD^3~2
.
From the local to the remote: push
To push all consistent commits from the local repo to the remote repo:
$ git push origin <branch>
If flag -u
or --set-upstream
is added, you set up a tracking reference so that you can type only git push
or git pull
and so on.
If you have inconsistent commits, causing Git refuses to push, you add the flag -f
or --force
, or use a +
before the branch as in +master
. This forces every local commit to overwrite its remote counterpart, and it may cause the remote repo to lose data. Think twice before using it!
From the remote to the local: clone, fetch, pull, reset
To clone everything from the remote repo into a new subdirectory of the current working directory (where the repo for the blog is taken for instance):
$ git clone <remote_url>
Fetching creates a local copy of a remote branch only, not affecting the working tree nor the head. To fetch everything from a remote branch:
$ git fetch origin <branch>
Meanwhile, pulling not only fetches a remote branch as said, but also merges all conflicts into the corresponding local branch. To pull from origin to a branch:
$ git pull origin <branch>
It is more straightforward, I think, to fetch and merge explicitly, than just to pull.
If there are local changes, which you are willing to discard, you may reset the local branch to a remote branch:
$ git reset --hard origin/<branch>
From the local to the tree: reset, revert
By resetting, you may completely restore the working tree to a previous state, by:
$ git reset HEAD~2
Flag --soft
rewrites changes not committed, leaving staged changes. Flag --mixed
rewrites changes not committed or not staged, leaving changes in the working tree. Flag --hard
rewrites changes not committed or not staged, and the working tree.
Meanwhile, by reverting, you may restore the working tree to a previous commit, but creating a new commit without rewriting the history:
$ git revert <commit_pointer>
Sometimes you want to rewrite the history, to combine several commits as one. To combine the last 5 commits as one:
$ git reset --soft HEAD~5
Afterwards, commit.
Instead, if you only want to reset one file, use:
git checkout HEAD~5 -- <certainfile.txt>
❧ February 6, 2017; revised July 30, 2021
References
❉ Git, Documentation
❉ S Puisungnoen, Git—the simple guide
❉ R E Silverman, «Git Pocket Guide». O’Reilly Media, 2013.
❉ NDP Software, Git cheatsheet