This article describes simple guidelines for setting up and using Git.
Git is a popular version control system, used to develop and maintain software in several scientific projects. This article describes simple guidelines for setting up and using Git. Using these guidelines, you can stay out of serious trouble and be more productive.
Guidelines [guidelines]
- Set up minimal global settings right away on every new computer.
- Create proper logical commits and commit messages.
- Create small local "checkpoint" commits then cleanup with 'git rebase -i'.
- Create local commits before running any commands that might accidentally modify/overwrite uncommitted changes.
- Backup local branches every few hours of work to remote Git repo on remote machine.
- You can always recover an earlier state of any of your local branches.
- Never delete a local Git repo unless you are completely done with it.
- Do not commit large generated (binary) files in a Git repo without careful consideration.
- Avoid
git push -f
to a remote branch shared with other people.
Set up minimal global settings right away on every new computer [minimal-setup]
Always set up a consistent global Git user.name
and user.email
on every machine where you use Git.
(Otherwise you will show up as many different developers according to Git, and it is a pain to resolve these in all of the Git repos you commit to after the fact).
Also, disable push of all branches by default (prior to Git 2.0) or a simple git push
will push all branches.
In addition, it is nice to see Git output with color (default is no color).
And, to avoid having to resolve the same merge conflicts multiple times, consider turning on the git rerere
feature.
To set these on a new machine, run:
$ git config --global user.name "First M. Last" # CRITICAL
$ git config --global user.email "youremail@someurl.com" # CRITICAL
$ git config --global color.ui true # Use color in git output to terminal.
$ git config --global push.default simple # Or 'tracking' with older versions of git.
$ git config --global rerere.enabled 1 # Auto-resolve same conflicts on rebase.
Also consider setting up your bash shell prompt and git
command-completion by downloading the bash scripts git-prompt.sh and git-completion.bash and add activating them by adding them to your ~/.bash_profile
file with the lines:
source ~/git-prompt.sh
source ~/git-completion.bash
PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
These bash scripts make using Git on the command-line much easier and more productive.
Create proper logical commits and commit messages [logical-commits]
Creating good commits with good commit messages is important for many reasons. Commits should contain a single logical change (see "SEPARATE CHANGES" in gitworkows(7) and "One Commit per Logical Change Solution" in the Udacity Git course). Commit messages should have a short summary line (under 50 chars is the target) and an optional longer body separated by a blank line (see guidelines in How to Write a Git Commit Message). For example:
Summary line for changes (50 chars is target but a little longer okay)
More detailed explanatory text in the body (wrapped to about 72 chars).
The blank line separating the summary from the body is critical to make
commands like 'git log --oneline', 'git rebase -i', and others readable
and useful.
If you use an issue tracker, put references to them like:
Resolves: #123
Also see: #456, #789
Create small local "checkpoint" commits then cleanup with git rebase -i
[small-commits-rebase-i]
To provide for easy local "undos" and better organization of changes into final change-sets, commit often locally using "checkpoint" commits (convention is to use commit summary lines starting with "WIP:").
But before pushing these commits to a remote shared branch, use git rebase -i @{u}
to clean up and reorganize the commits into good "logical" commits (see "SEPARATE CHANGES" above).
Create local commits before running any commands that might accidentally modify/overwrite uncommitted changes [uncommitted-changes]
The commands git pull
, git merge
, git rebase
, or other Git operations can alter (or
delete) your local uncommitted changes, either in the working directory or the staging
area/index.
So always create (sometimes temporary) commits for these before running any of these commands (unless you want to throw away uncommitted changes in your local repo, for example with git checkout
, git reset
, git clean
, etc.).
Backup local branches every few hours of work to remote Git repo on remote machine [backup-frequently]
This is to safeguard your work in case your local machine or disk goes out or your local .git/
directory becomes corrupted somehow.
(Local Git branches are better than Git stashes because you can back them up to other repos in a version controlled way.
You can’t do that with Git stashes.)
You can always recover an earlier state of any of your local branches [recover-previous-state]
Assuming you have been committing your changes locally, to recover an earlier state, run git reflog
and then use a combination of git checkout
and/or git reset –hard
, etc.
(See How to undo (almost) anything in Git.)
Never delete a local Git repo unless you are completely done with it [dont-delete-and-reclone]
Your local Git repos have a wealth of information that can’t be pushed to other Git repos (e.g. git rerere
info, git reflog
info, etc.).
If you have an escape plan (see above), you should never have to delete a local Git repo and re-clone to get out of some "bad" state.
Only a corrupted disk that corrupts the local Git DB history (which is extremely rare) should cause you to have to re-clone the local Git repo.
(If you feel like you need to delete your local Git repo to get out of some bad state of a non-corrupted repo, then you have not yet learned the basics of Git well enough so keep learning!)
Do not commit large generated (binary) files in a Git repo without careful consideration [beware-binary-files]
Most revision control systems, and Git is no exception, are optimized to handle text/ascii files. They don't do well with binary files, especially large binary files. Big generated (binary) files committed to a git repo get stuck in the Git history forever and can only be removed by "filtering" the Git repo (which is a very disruptive process for everyone involved). That said, sometimes handling binary files in a Git repo cannot be avoided in which case consider using Git Large File Storage (Git-LSF) support. Git-LFS will add complexity to your workflows but also save you from clogging history.
Avoid git push -f
to a remote branch shared with other people unless everyone involved really knows what they are doing [avoid-force-push]
Very few Git users know how to adjust to a forced reset remote branch or even what that means. (However, if everyone involved knows how to adjust with a forced pushed reset branch to a (temp) shared branch or if the branch is not shared, then forced pushes are fine.)
Conclusion
There are many other helpful guidelines that you can come up with for using Git but the ones above are arguably the most helpful for Git beginners (and some people that have been using Git for many years but never learned these basic guidelines).
This article was originally published on May 18, 2021.