Git
My git cheat sheet! See also: svn and hg
This might also be useful: http://git.or.cz/course/svn.html#branch
/etc/gitconfig
Commands
command | description |
---|---|
git clone ${path} | retrieves the entire git repository to your local disk |
git clone --mirror --bare ${path} | clones the repository, use git fetch --all later to update it
|
git pull | pulls any new revisions from the original path |
git push | pushes local revisions to the original path |
git commit | commits to the LOCAL repository |
git status | status since last commit |
git tag | lists the avaliable tags |
git show ${branch/commit/tag} | show details of the commit or tag |
git checkout ${branch/commit/tag} | changes the working copy to the tag specified |
git reset --hard | reverts all changes, to the currently checked out tag |
git reset --soft HEAD^ | reverts the HEAD pointer to the previous, but KEEPS your changes and index |
git reflog | shows a simple log with 7 characters of the has, refspec and commit message |
git fsck | shows information about dangling blobs/commits etc... |
git fetch ${remote-repo} ${remote-branch}:${local-branch} | fetches the remote branch |
git push origin master:master | first-time push |
git push ${remote-repo} ${remote-branch}:${local-branch} | push the branch |
git remote add ${local-identifier} ${remote-address} | add a remote server that you are able to push to |
git branch -a | list all branches remote and local |
|
|
git branch ${branch} -u ${remote/branch} | setup the existing branch to track remote/branch |
git apply ${patch-file} | apply a patch |
git archive ${branch/commit/tag} | output a tarball of the given tag to stdout |
~/.gitconfig
[user] name = "Attie Grande" email = "attie@attie.co.uk" signingkey = 0x........ [alias] st = status ci = commit -v co = checkout re = remote -v br = branch -va fe = fetch -p dc = diff --cached p5 = push origin master~5:master tg = tag -s lg = log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --date-order lg2 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --date-order [color] ui = true [push] default = simple [credential] helper = store
First push into a fresh repository
git add x y z git ci -m "first" git push origin master
Test for a repository
REPO=$(GIT_DIR=${TEST_DIR} git rev-parse --git-dir 2>/dev/null)
Delete all untracked files
BE CAREFUL WITH THIS
rm -rf $(git st | awk 'BEGIN{ keep=0 }{if ($0 == "# Untracked files:") { keep = 1 } else if (keep == 1 && NF == 2) { print $2 } }')
Redo last commit
git commit ... git reset --soft HEAD^ # 1 # edit files # 2 git add .... # 3 git commit -c ORIG_HEAD # 4
- This is most often done when you remembered what you just committed is incomplete, or you misspelled your commit message, or both. Leaves working tree as it was before "reset".
- Make corrections to working tree files.
- Stage changes for commit.
- "reset" copies the old head to .git/ORIG_HEAD; redo the commit by starting with its log message. If you do not need to edit the message further, you can give -C option instead.
Merging
There are a few ways to merge. These are the useful arguments
--ff-only | This is useful when you are trying to merge a change from another branch, and this branch hasn't changed in the meantime |
--no-ff | generate a merge commit even if it could have been fast forwarded |
--log | add the one-line messages from commits merged |
--stat | show stats after the merge |
Rename a remote (and local) branch
git branch -m master master-old git push remote :master # delete master git push remote master-old # create master-old on remote git checkout -b master some-ref # create a new local master git push remote master # create master on remote
You may need to change your .git/config
file to update the remote branch tracking
This can also create issues for people who have the re-named branch checked out...
Modify committer's name/email
git filter-branch --commit-filter ' if [ "${GIT_COMMITTER_NAME}" = "${OLD_NAME}" ]; then GIT_COMMITTER_NAME="${NEW_NAME}"; GIT_AUTHOR_NAME="${NEW_NAME}"; GIT_COMMITTER_EMAIL="${NEW_EMAIL}"; GIT_AUTHOR_EMAIL="${NEW_EMAIL}"; git commit-tree "$@"; else git commit-tree "$@"; fi' HEAD
Import SVN history into a new GIT repoistory
Extract an SVN subtree - Import into Git
Simples! The 'users.txt' file looks like this:
attie = Attie Grande <attie@attie.co.uk>
git svn init http://subversion/repo --no-metadata ./repo cd repo git config svn.authorsfile ../users.txt git svn fetch git remote add origin /path/to/new/git/repo git push origin master:master
Delete a tag from the remote repository
git tag -d 12345 git push origin :refs/tags/12345
Bisect
git co -b bug_hunting # first create a branch from where you are git bisect start git bisect bad HEAD # you are probably at a bad commit already... git co ${TAG_OR_COMMIT} # locate a good commit, jumping back large chunks at a time, e.g: release tags git bisect good HEAD # once you have a good commit
Git will now checkout a commit between the commits you marked as 'good' and 'bad', you should now re-build the system or test it to determine if this commit is good or bad.
Once you have determined the quality of this commit, run git bisect good HEAD
or git bisect bad HEAD
and you will be presented with another commit to try.
When git has done everything it can, you will be presented with something like this:
e5c4076f317a050db38cd4cc7fc8f6c95f4d79e8 is the first bad commit commit e5c4076f317a050db38cd4cc7fc8f6c95f4d79e8 Author: Attie Grande <attie@attie.co.uk> Date: Mon Feb 27 20:18:05 2012 +0000 tidied up as much as possible when client disconnects :100644 100644 fecca9786415c209e2d62998e39c07a7134c873b 2678b82757ffa7d0c76983af652652368c5f1067 M TODO :100644 100644 fa88798b08649a176f5f9e00d4fb959841b8c07c 0d28402348ece19788b6c6818148723022d959d2 M net.c :100644 100644 23f3c4cd8f12fab264e4d007474d53df3bb5f3b5 e0ab1dfde0c5ed3dd28e0b12d5d2d1a0d47fe482 M net_io.c
Git is now showing you the first bad commit (e5c4076f317a050db38cd4cc7fc8f6c95f4d79e8
).
The files mentioned are those that were modified in this commit.
Doing a command like git diff 23f3c4cd8f12fab264e4d007474d53df3bb5f3b5 e0ab1dfde0c5ed3dd28e0b12d5d2d1a0d47fe482
will show you the changes in the relevant file (net_io.c
- the problem file!).
The bisect tool is just another argument for many small commits - the will be a smaller diff to wade through!
Authentication (HTTP)
If you're using HTTP to access a repository, you can add the following lines to your configuration files:
~/.gitconfig
[credential] helper = store
~/.git-credentials
http://username:password@server/
Committing with a specified timestamp
Use the GIT_AUTHOR_DATE
and/or GIT_COMMITTER_DATE
environment variable.
For example, +/- xhrs:
#!/bin/bash -ue if [ $# -lt 2 ] || [ "$1" == "" ]; then echo "$0 [+|-]<hrs> command ..." exit 1 fi HRS=$1 shift if [ "`echo ${HRS} | cut -b1`" != "+" ] && [ "`echo ${HRS} | cut -b1`" != "-" ]; then HRS=+${HRS} fi DATE=$(date -d @$(echo $(date +%s)${HRS}*60*60 | bc)) export GIT_AUTHOR_DATE=${DATE} export GIT_COMMITTER_DATE=${DATE} git "$@" unset GIT_AUTHOR_DATE unset GIT_COMMITTER_DATE
Getting the first tag that contains a file
Tig?
#!/usr/local/bin/bash if [ "$1" == "" ]; then echo "usage: $0 <filename>" exit 1 fi if [ ! -e $1 ]; then echo "$0: File does not exist ($1)" exit 1 fi echo -en "Finding first commit..." COMMIT=`git log --pretty=oneline "$1" | tail -n 1 | cut -d " " -f 1` if [ "$COMMIT" == "" ]; then echo "$0: Error while retrieving commits for file \"$1\"" exit 1 fi echo -en "\rFinding tags containing commit $COMMIT..." git tag -l --contains "$COMMIT" > /tmp/tag_contains if [ "$?" != "0" ]; then echo "$0: Error while retrieving tags containing commit \"$COMMIT\"" exit 1 fi echo -en "\rFinding first tag that contains $COMMIT..." git for-each-ref --sort='-*authordate' --format='%(tag)' refs/tags/ | while read a; do if [ "$a" == "" ]; then continue fi grep "$a" /tmp/tag_contains > /dev/null if [ "$?" == "0" ]; then LAST=$a else echo "$LAST" > /tmp/tag_first break fi done TAG=`cat /tmp/tag_first` rm /tmp/tag_contains /tmp/tag_first echo -en "\rFinding tag information..." INFO=`git show "$TAG" | head -n 3 | tail -n 2` if [ "$INFO" == "" ]; then echo "$0: Error retrieving info for tag \"TAG\" (maybe it isn't annotated?)" exit 1 fi echo -en "\r\0033[K" echo -e "File:\t\t$1" echo -e "First tag:\t$TAG" echo "$INFO" | sed -re 's/^(.+):[ ]+(.+)$/\1:\t\t\2/'