Git Quick Reference
Good resources are listed at the home page documentation.
Especially good references are:
- git concepts simplified
- Git for Computer Scientists
- Understanding Git Conceptually
- Git Best Practices
Git configuration (first time only)
You can either edit ~/.gitconfig by hand, or run git config ... to change the settings.
Define your identity with:
git config --global user.name "Firstname Lastname" git config --global user.email "email@example.com"
Set up one useful alias:
git config --global alias.la "log --all --graph --date=short --format=format:\"%C(yellow)%h%Creset %ad%Cred%d %Cblue%an%Creset %s\""You can then run git la to "log all" history.
If on OS X, tell git to remember your passwords in the keychain:
git config --global credential.helper osxkeychain
If on OS X, tell git to not trust ctime:
git config --global core.trustctime false
Working with GitHub
We use two different models of collaboration on GitHub:
- Centralized, for papers, proposals, etc. Here everyone has write access to a single repository and there are no forks or branches. Everyone directly pushes and pulls to the centralized repository.
- Distributed, for source code. Here there is a main repository that only one person has write access to. Everyone else forks this repository, works on branches, pushes to their own fork, and issues pull requests (PRs) back to the main repository.
GitHub: centralized model
Starting the project: (project owner only) Make a repo on GitHub called paper_name and a team also called paper_name. Add the repository to the team, set team permissions to "write access", and add people to the team.
Getting started as a collaborator: Everyone should clone the main repository:
git clone firstname.lastname@example.org:compdyn/paper_name.git
The central repository will be called origin.
Making changes: Always stay on the master branch. Edit files locally, then add/commit. To push changes to the central repository do:
git push origin master
If the push fails due to newer changes on the origin, you need to update (see below) and then push again.
Getting changes: Before getting changes from the central repository, make sure you have committed all your local changes. Check this with git status. Then do:
This will merge remote commits with your local commits (if any).
Resolving conflicts: The only time when conflicts can occur is during a git pull. Doing local git commit will always succeed, and git push will simply stop if everything isn't up to date already. To fix a conflict, do git status to see which files need fixing (they are the ones that aren't added to the index). Edit these files (look for <<<<<< ====== >>>>>> sections), then git add them. Once all files are fixed and added, do git commit.
Important note: When working with a centralized model it is important to push and pull frequently to keep everyone synchronized. Always pull before starting work each day, and commit/push frequently (at least once per day, or much more often if multiple people are working simultaneously on the same repository).
GitHub: distributed model (for contributors)
Getting started as a collaborator: Everyone should fork the main repository on GitHub. Assuming the main repository is in an organization called org, so it's full name is org/code_name, then the forked version for user user_name will be user_name/code_name. Next, clone the forked repository to your local machine and set up the main repository as the upstream (cf. Fork a repo on GitHub help):
git clone email@example.com/user_name/code_name.git git remote add upstream firstname.lastname@example.org/org/code_name.git
This means that you now have three key repositories to keep track of:
- Upstream: the main central repository on GitHub. You can't directly push to this, but this is where you will pull other people's commits from.
- Origin: your forked repository on GitHub. You can push and pull directly to this.
- Local: your clone of origin on your local computer. This is where you commit before pushing to origin.
Important note: Don't ever commit anything to the master branch. Only the upstream owner should ever commit to master. You should do all your work in branches and issue pull requests on these branches back to upstream.
Updating your fork from upstream: Getting new changes from upstream is a two-step process. First you pull from upstream to your local repository, then you push the new changes back to your origin. There is no direct communication between upstream and your forked origin repository. Note that for this to work it is critical that you have never committed anything to your master branch. The procedure to pull and then push is:
git checkout master # make sure you are on the master branch git pull upstream # pull new changes from upstream git push origin master # push the new changes back up to your fork (origin)See also the GitHub help pages on Syncing a fork and Pushing to a remote.
Editing, committing, and pushing your code: You should only ever commit and push code on a branch (never on master). To start a new branch, do:
git checkout -b branch_name
Later, you can do:
git checkout branch_name # make sure you are on the right branch # ... edit code git add <code> git commit -m "<message>" git push origin branch_name
This makes local code changes and then pushes them up to your forked repository (origin).See also Pushing to a remote on the GitHub help pages.
Merging your code back into upstream and master: You should never merge your branches into your own master. Instead, issue Pull Requests (PRs) to have them merged back into the upstream master by the owner of upstream. To do this:
- Go to the GitHub page for your forked repository.
- Switch to the branch that you want to merge using the branch dropdown.
- Click the green compare-and-review button (with two tip-to-tail arrows making a square).
- Click the green "Create pull request" button.
Once the upstream owner merges your code, you can then get it back into your master by updating your fork from upstream, and then you can delete your branch that was merged. See also Using pull requests on GitHub Help.
GitHub: distributed model (for owners)
Starting the project: Make a repo on GitHub called code_name and a team also called code_name. Add the repository to the team, set team permissions to "read access", and add people to the team. If there is going to be more than one maintainer with direct write access, then make a code_name_maintainers team with "write access". Alternatively, if this is a public repository with just one owner/maintainer then no teams are needed.
- Main repository: ssh://lagrange.mechse.illinois.edu/~mwest/public_git/partmc.git
- Matt's private repository: ssh://lagrange.mechse.illinois.edu/~mwest/public_git/partmc_private.git
- Private repositories for other users: ssh://lagrange.mechse.illinois.edu/~<username>/public_git/partmc.git
To clone the main repository on your laptop:
git clone ssh://lagrange.mechse.illinois.edu/~mwest/public_git/partmc.gitTo publish your own private repository, on lagrange first do:
mkdir ~/public_git git init --bare ~/public_git/partmc.gitThen on your laptop in your partmc repository do:
git remote add lagrange ssh://lagrange.mechse.illinois.edu/~<username>/public_git/partmc.git git config remote.lagrange.push '+refs/heads/*:refs/heads/*' git push lagrange
To get branches from another repository owned by username:
git remote add <username> ssh://lagrange.mechse.illinois.edu/~<username>/public_git/partmc.git git fetch <username> refs/heads/<branchname>:refs/remotes/joined/<branchname> # just one branch git fetch <username> # all branches
To look at a remote branch from <username> for the first time:
git checkout <branchname> <username>/<branchname>Thereafter it's just:
git checkout <branchname>
To update your local copy of a remote branch to the current value of a remote repository, do:
git checkout <branchname> git pull <username>In the case of the master branch this is just:
git checkout master git pull origin
To set up a push repository on taub, do:
taub$ git init ~/partmc taub$ module initadd git # make sure "module load git" is in .bashrc, not .bash_profileThen on the local laptop do:
laptop$ git remote add taub ssh://taub.campuscluster.illinois.edu/~<username>/partmc laptop$ git config remote.taub.push '+refs/heads/*:refs/heads/*' laptop$ git push taubThis will complain about not updating a currently-checkout-out branch. To fix this, just checkout a different branch on taub then push again.
PartMC branches and tags
PartMC version numbers have the format major.minor.patch. Patch-level changes are only for bugfixes.
- master - current development branch
- 1.0, 1.1, 2.0 - release branches
- all other branches are for private feature development
- 1.0.0, 1.0.1, 1.0.2 - releases on the 1.0 branch, corresponding to partmc-1.0.X.tar.gz release tarballs.
Main repository topology:
* master branch | * 2.1 branch, 2.1.4 tag | * 2.1.3 tag | * 2.1.2 tag | * 2.1.1 tag | * 2.1.0 tag |/ * 2.0.0 tag | * 1.2 branch, 1.2.1 tag |/ * 1.2.0 tag | * 1.1 branch, 1.1.1 tag | * 1.1.0 tag |/ * 1.0.0 tag
Difference between different states of code:
git diff oldbranch..newbranch filename # diff of one file from oldbranch to newbranch git diff oldbranch..newbranch # diff of all files from oldbranch to newbranch git diff --stat oldbranch..newbranch # show which files changed from oldbranch to newbranch
Delete remote tracking branches that have been deleted on the remote side:
git remote prune REMOTENAME
Find a git commit that introduced a change:
git log -Ssearchtext # search everything git log -SFoo -- path_containing_change # for just one fileSee also --pickaxe-regex argument to git log.
Undo git add FILENAME:
git reset FILENAME
Undo a git rm FILENAME:
git checkout HEAD --
Undo the last commit:
git reset --soft HEAD^ # leaves things staged and in working tree git reset --mixed HEAD^ # leaves working tree alone but unstages files git reset --hard HEAD^ # resets both index and working tree
Diff by words (rather than lines):
git diff --word-diff PREV_REV..NEW_REV git diff --word-diff=color PREV_REV..NEW_REV git diff --word-diff=plain PREV_REV..NEW_REV git log -p PREV_REV..NEW_REV git log -p --word-diff PREV_REV..NEW_REV git log -p --word-diff=color PREV_REV..NEW_REV git log -p --word-diff=plain PREV_REV..NEW_REV
Delete a remote branch:
git push REMOTENAME :BRANCHNAME
Diff or log a branch from a common ancestor of the master branch:
git log BRANCHNAME ^master # commits reachable from BRANCHNAME but not from master git diff master...BRANCHNAME # special syntax that only works for diffNote that git log treats "..." like git rev-list does, which is very different to how git diff treats it (confusingly, git rev-list uses "..." to mean symmetric difference, which is more like how git diff uses "..").
Copy a specific file on a different branch:
git checkout revision -- filename # checkout just one file git checkout revision -- directory # can also do whole directories git show revision:path/to/file > local_file # stores in a different location
Push specific revisions:
git push remotename : # push matching branches git push remotename tag tagname # push just one tag