GIT notes by Simon PJ
Here are notes about using Git that Simon PJ has found useful.
Understanding the model
See WorkingConventions/Git/Submodules for the GHC specific stuff.
Suppose you have a submodule utils/haddock in the main GHC repo.
- The submodule utils/haddock is a full-on, independent Git repo
- You should think of the GHC repo as having a file that contains the commit-id (e.g. ac60bd1) for the utils/haddock repo. That's all that the GHC repo remembers about the utils/haddock repo. But it means that the GHC repo knows the exact state of the utils/haddock repo that matches the state of the GHC repo.
- In the GHC repo, git submodule update utils/haddock checks out the utils/haddock repo to match the GHC repo's recorded commit-id (in this case ac60bd1). If you do this for all submodules, they'll all line up with a particular state of the GHC repo.
Push only the current branch
When you say git push (with no arguments), push only only patches on the current branch. If you have un-pushed commits on other branches, leave them be.
git config --global remote.origin.push HEAD
Creating tracking branches
Here is very useful info on tracking branches.
Suppose you create a new branch on your local machine. Now you want to push it up to the global repo. You almost certainly want your local branch to become a tracking option of the remote one, so that git pull will merge changes to the remote copy into your local copy.
git config --global branch.autosetupmerge true
Global .gitignore file
Here's how to set up a global (across all your projets) .gitignore file.
- Put the file somewhere, eg $(HOME)/.gitignore. The patterns are one per line; e.g. *.~[0-9]*~ to ignore emacs backup files
- Execute this command
git config --global core.excludesfile $(HOME)/.gitignore
Looking at the current state of affairs
Show one-line-per-file diff summary
Show a one-line-per-file summary of diffs between working files and the local repo:
git diff --stat
Show delta between branch and trunk
Show the commits that are on branch my-test but not on the main trunk:
git log `git merge-base master my-test`..my-test
The git merge-base b1 b2 thing returns the name of the commit that is the common ancestor of branches b1 and b2.
Working with branches
Create a branch after doing some edits
You are sitting on a branch (say master), and do some edits. Now you decide it wasn't as simple as you thought so you want to create a branch to keep your edits safe while you do something else.
git checkout -b <new-branch-name>
This creates the new branch and switches to it, but does not change your working files. Now you can safely commit on the branch Stackoverflow link. Then to push to the master repo:
git push origin <new-branch-name>
That will create <new-branch-name> in the master repo if it does not already exist.
Work on a branch gotten from the main repo
You have done a git fetch to get the upstream repo, which has a branch origin/experiment. You want a local experiment branch which tracks origin/experiment:
git checkout --track origin/experiment
- creates a local branch experiment,
- sets it up to track origin/experiment, and
- checks it out
It will fail if local branch experiment already exists -- in that case you may want to do the --set-upstream thing (see next item).
If git doesn't know that origin/experiment is a branch, the git checkout command interprets origin/experiment as a filename, and outputs the confusing message
fatal: git checkout: updating paths is incompatible with switching branches. Did you intend to checkout 'origin/experiment' which can not be resolved as commit?
You probably want to do a git fetch, then git branch -r to see what remote branches there are.
Connect up a local branch with its remote counterpart
You are on local branch experiment and do git pull to pull down changes from origin/experiment, but you get this:
You asked me to pull without telling me which branch you want to merge with, and 'branch.experiment.merge' in your configuration file does not tell me, either. Please
Somehow you in a state where experiment isn't tracking origin/experiment. To make it tracking, use --set-upstream:
git branch --set-upstream experiment origin/experiment
Undoing a commit you wish you hadn't made
If you have not yet pushed, you can just back up the head pointer one step:
- git reset --soft HEAD^
If you have pushed, you make a commit that exactly undoes what you did, and push that:
- git revert HEAD
git gui on Windows
I’ve been using git gui (on Windows at least) as a way to examine and stage changes. But I suddenly found that it wasn’t displaying the diff in the main pane.
A google search http://code.google.com/p/msysgit/issues/detail?id=394 suggested that (bizarrely) it might have something to do with ‘nice’.
So I renamed c:/cygwin/bin/nice.exe to c:/cygwin/bin/cygin-nice.exe, and that made git gui worked fine. Wierd.