- Last updated: 12 March 2024
- Author: Tijmen de Haan
In contrast to CVS or SVN, each Git repository is created equal. Repositories all contain the entire history, and there are no client/server designations built into Git. You may choose to use Git in any topology you'd like, though a traditional central server is still very common. These days we often choose this central server to be a Git hosting platform like GitHub.
An advantage of distributed version control is that everyone's copy serves as a complete backup. As an example, in 2011 kernel.org went down due to a security breach. The distributed nature of Git allowed development of the Linux kernel to continue relatively unaffected.
-
Introduce yourself to Git:
git config --global user.name "Your Name" git config --global user.email [email protected]
-
Enable color output:
git config --global color.ui auto
-
Choose your default text editor:
git config --global core.editor nano
-
Set default push behavior:
git config --global push.default current
-
Create a new repository:
git init
-
Create a bare repository:
git init --bare
- Working tree: files and folders on your filesystem except the .git folder
- Staging area: files added with
git add
are staged for commit - Repository: each commit is a snapshot of the entire tree
- Remotes: other repositories (often this will be GitHub)
The commands you'll likely use most frequently are: add, commit, push, and pull.
Stage changes from your working tree for commit. Use git add <file>
for specific files or git add .
to stage all modifications in the current directory.
Commit to your staged changes locally with git commit -m "Your message"
. This moves your changes (file changes, new files, deletions, etc.) from your staging area into your local repository.
Send commits from your local repo to a remote one with git push origin <branch>
. This updates the remote repository with your local changes.
Fetch and merge changes from the remote repo to your local one using git pull origin <branch>
. Essential for keeping your local repo up-to-date.
-
Create a new branch:
git branch feature
-
List branches:
git branch git branch -a
-
Switch branches:
git checkout main git checkout feature
-
Merge changes and delete branch:
git checkout main git merge feature git branch -d feature
-
Discard branch changes:
git checkout main git branch -D feature
-
Cherry-pick a specific commit:
git cherry-pick a43b72f
These days it's very common to use GitHub to manage remote repositories.
-
Add a remote repository:
git remote add origin https://github.com/username/repo.git
-
List remote repositories:
git remote -v
-
Fetch changes from a remote repository:
git fetch origin
-
Pull changes from a remote repository:
git pull origin main
-
Push changes to a remote repository:
git push origin main
Provide descriptive commit messages. If you ever need to use a shared account (such as the southpoletelescope user that runs SPT), sign commits by hand e.g. "TdH: Added a git tutorial."
Good commit message example:
Add parallel processing feature with multiprocessing.Pool. Checks available number of CPUs N and chooses min(N,8) threads. Unit tests passed.
Bad commit message example:
Fixed bugs
-
View global history:
git log
-
View history for a specific file:
git log -- path/to/file
-
Compare versions:
git diff 51ad6f..23eba2 -- path/to/file
-
Compare recent commits:
git diff HEAD^^..HEAD
-
Compare working tree and staging area:
git diff
-
Store untracked changes:
git stash
-
Re-apply stashed changes:
git stash pop
-
If you're not sure what's in the stash, try:
git stash list
When working in a configuration where there is one central server that all users pull from and push to, it can happen that you go to push only to find out that there were some trivial changes made in some other part of the repository. In this case, git pull
will create a merge, which will be a separate commit that clutters up the history. However, in these cases it is better to git pull --rebase
to reapply your recent commit on top of the current state of the remote.
-
Reset working tree to the current repository state:
git reset --hard HEAD
-
Reset local repository to an earlier commit:
git reset --hard 154bf2
-
Undo the latest commit:
git reset --hard HEAD^
-
Interactive rebasing (avoid rewriting pushed history):
git rebase -i
-
Use
git revert
to create a new commit that undoes the changes made in a previous commit without rewriting history:git revert a43b72f
When merging branches or pulling changes from a remote repository, you may encounter merge conflicts if the same lines of code have been modified in different ways. To resolve merge conflicts:
-
Open the conflicting files and look for the conflict markers (
<<<<<<<
,=======
,>>>>>>>
). -
Manually edit the files to resolve the conflicts by choosing the desired changes and removing the conflict markers.
-
Stage the resolved files using
git add
. -
Commit the changes to complete the merge:
git commit -m "Resolve merge conflicts"
Git hosting platforms provide a cloud-based remote. The most popular ones are:
-
GitHub
- By far the most popular at the moment.
- Provides a large community and a vast ecosystem of integrations and tools.
-
GitLab
- Offers a complete DevOps platform with built-in CI/CD, issue tracking, and project management tools.
- Provides both cloud-hosted and self-hosted options.
-
Bitbucket
- Integrates well with Atlassian's suite of tools like Jira and Confluence.
- Offers free private repositories for small teams.
These platforms have built-in issue trackers, wikis, discussion sections, access control, etc.
Pull requests are a particularly useful feature, allowing you to propose changes to a repository and assign reviewers to that change. When the reviewers approve, they can merge your changes into the main branch.
Git workflows provide guidelines for structuring your branching and merging strategies. Two common workflows are:
-
Gitflow Workflow
- Consists of two main branches:
main
(previouslymaster
) anddevelop
. - Feature branches are created from
develop
and merged back intodevelop
when completed. - Release branches are created from
develop
, tested, and merged intomain
for production releases. - Hotfix branches are created from
main
for critical bug fixes and merged back into bothmain
anddevelop
.
- Consists of two main branches:
-
Feature Branch Workflow
- Each new feature or bug fix is developed in a separate branch.
- Feature branches are created from the main branch (e.g.,
main
) and merged back via pull requests. - This workflow is simpler and more flexible than Gitflow, making it suitable for smaller teams or projects.
Choose a workflow that aligns with your needs.
-
Write clear and concise commit messages that describe the changes made in each commit.
-
As much as possible, keep commits focused on a single logical change to maintain a clean and readable history.
-
Regularly pull changes from remote repositories to stay up to date and avoid merge conflicts. Remember to use
git pull --rebase
if appropriate. -
Use descriptive branch names that reflect the purpose of the branch (e.g.,
feature/multiprocessing
,bugfix/indexing-error
). -
Avoid pushing unfinished or untested code to the main branch.
-
Perform code reviews and use pull requests to ensure code quality and collaboration.
-
Use tags to mark important milestones or releases in your project.
-
git bisect
: Helps you find the commit that introduced a bug by performing a binary search through the commit history.git bisect start git bisect bad 23eba2 git bisect good 51ad6f
-
git reflog
: Allows you to view and recover lost commits or branch references.git reflog
shows the history of all actions performed in the repository, including commits, branch switches, and resets.- A "lost commit" refers to a commit that is no longer reachable from any branch or tag, often due to a reset or branch deletion. Similarly, a "lost branch reference" refers to a branch that has been deleted or overwritten.
- To recover a lost commit or branch, find the desired commit in the reflog output and use
git checkout
to switch to it:git reflog git checkout 154bf2
-
git blame
: Shows the author and commit information for each line of a file.git blame path/to/file
GUI tools like GitKraken, GitHub Desktop, gitg, gitk, or SourceTree are useful for visualizing repository history and changes.
Git hooks are scripts that Git executes before or after events such as: commit, push, and receive. They allow you to customize Git's internal behavior and trigger customizable actions at key points in your work flow.
Here are some examples of git hooks you could consider:
- pre-commit hook: code linter to check for code quality and style
- pre-commit hook: commit message check for style or required information
- pre-commit hook: security check to look for API keys or other sensitive information
- pre-push hook: run unit tests to make sure the code is functional
- post-commit hook: generate a documentation or version number
- pre-rebase hook: make sure the latest changes from the remote have been pulled in
- etc.
Tags are used to capture a point in history that is used for a e.g. a version release.
-
Create a tag:
git tag -a v1.0 -m "Version 1.0"
-
Push a tag to remote:
git push origin v1.0
-
List all tags:
git tag
Aliases are used to create shorter commands that map to longer commands.
-
Create an alias:
git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.st status
-
Use an alias:
git co main
-
Create aliases for complex commands or sequences of commands using shell scripts or Git's
!
syntax:git config --global alias.release '!./release.sh'
Submodules allow you to keep a Git repository as a subdirectory of another Git repository. This lets you clone another repository into your project and keep your commits separate.
-
Add a submodule:
git submodule add https://github.com/username/repo.git
-
Update submodules:
git submodule update --remote repo
There is also git subtree
which is similar but integrates the external module more tightly with the main repo. git submodule
requires the developer to be aware of the submodule and manually keep it up to date, while git subtree
is less visible to the developer.
- Git Cheat Sheet: https://training.github.com/downloads/github-git-cheat-sheet.pdf
- Atlassian Git Tutorial: https://www.atlassian.com/git/tutorials
- (humor) Git man page generator: https://git-man-page-generator.lokaltog.net/
I hope I have covered the basics of using Git for version control. Feel free to refer to this document as a cheat sheet and let me know at [email protected] if you have any suggestions for improvement.