Debian:
$ sudo apt-get install git
Cygwin:
$ setup.exe -p git $ apt-cyg install git
After install set up some options:
$ git config --global user.name "Oleksandr Gavenko" $ git config --global user.mail "gavenkoa@gmail.com"
After that you should have:
$ cat ~/.gitconfig [user] name = Oleksandr Gavenko mail = gavenkoa@gmail.com
Only http:// protocol support proxy (not git://):
$ export http_proxy="http://username:password@proxy:port/" $ git clone http://github.com/$user/$proj.git $proj
You can store proxy settings under repository local config file:
$ git config http.proxy http://$user:$passwd@$ip:$port
Setup proj space on fs:
$ mkdir proj $ cd proj $ git init Initialized empty Git repository in /home/user/tmp/proj/.git/ $ ls -a . .. .git
Add file, make changes, commit all:
$ emacs Makefile ... C-x C-c $ emacs app.c ... C-x C-c $ git add Makefile app.c $ git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: Makefile # new file: app.c #
or just:
$ git add .
Commit newlly added file:
$ git commit ... Write message log ... Created initial commit 2169263: My first commit massage. 1 files changed, 4 insertions(+), 0 deletions(-) create mode 100644 app.c
Show difference between index/stage and working tree:
$ git diff
Show difference between HEAD and index (what is going to be commited):
$ git diff --cached $ git diff --staged
Note
--cached and --staged are synonyms.
Show difference beetween HEAD and working tree (what is commited after git commit -a):
$ git diff HEAD $ git diff HEAD -- $path
Show difference in changeset:
$ git show $hash
Show difference between revisions:
$ git diff $rev1..$rev2 $ git diff ORIG_HEAD..HEAD
For merge first parent is a tip where merge is performed, second is a tip of merged branch.
Note
git show shows "combined diff": only files which were modified from all parents. git show --first-parent can be used to show how branch was chaged after merge.
Show differences to each parent for merge:
$ git show -m $hash
You do:
$ git add badfile $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: badfile #
To stop tracking badfile do:
$ git rm --cached badfile $ git status # On branch master # Untracked files: # (use "git add <file>..." to include in what will be committed) # # file nothing added to commit but untracked files present (use "git add" to track)
or:
$ git reset badfile
Individual file:
$ $EDITOR Makefile $ git add Makefile $ git diff --cached $ git commit -m "..."
Commit all changed and previously manages files:
$ git commit -a -m "...."
Print current branch:
$ git branch
List all known branches:
$ git branch -a
List all known remote branches:
$ git branch -r
List all remote branches directly from remote:
$ git ls-remote $ git ls-remote origin
List registered remotes:
$ git remote -v $ git remote $ git remote show
List remote branches from $REMOTE remote:
$ git ls-remote --heads $REMOTE $ git remote show $REMOTE
Special case of above is origin remote, which is default remote:
$ git remote show origin $ git ls-remote --heads origin
Note
Look to [remote "..."] in ~/.git/config to find out names of possible remotes. Alternatively get list from:
$ git remote show
Getting branches pointers from default (origin) remote (without merging tracking branch):
$ git fetch
Getting branches pointers from $REMOTE remote:
$ git fetch $REMOTE
To get updated with default remote changes:
$ git pull
or specify concrete remote:
$ git pull $REMOTE $ git pull origin
Delete local branch (-D is unsafe i.e. changes aren't pushed to any remote):
$ git branch -d $NAME $ git branch -D $NAME
Delete remote branch:
$ git push $REMOTE --delete $BRANCH_NAME $ git push $REMOTE -d $BRANCH_NAME $ git push origin -d $BRANCH_NAME
To locally remove pointers to deleted remotely branches:
$ git remote update --prune $ git remote update --prune origin
Note
Only curtain branches fetched by default:
[remote "origin"] url = ... fetch = +refs/heads/*:refs/remotes/origin/*
Edit fetch value to change defaults.
Move branch pointer to arbitrary hash:
$ git branch -f $NAME $HASH
Create local branch from remote with the same name:
$ git checkout --track origin/fix
Create local branch from remote with an alternative name:
$ git checkout -b myfix origin/fix
git does not directly support such feature. You can emulate it by:
$ git fetch $ git log master..origin/master # or just '..origin/master'
By previous commands you grab changes from remote server! You can apply them by pull or merge or rebase command:
$ git pull $ git merge TODO
To detect if remote repository have new changes:
$ git ls-remote $ git ls-remote $upstream
Review specific commit with:
$ git show $REV $ git diff $REV^ $REV
Review merge commit related to specific parent:
$ git diff $REV^1 $REV $ git diff $REV^2 $REV $ git diff HEAD^1 HEAD $ git diff HEAD^2 HEAD
Note
^1 is the first parent, ^2 is the second parent, and so on.
git show command for merge commits shows only changes from conflicting hunks. It is equivalent to (lines that changed as part of the conflict resolution):
$ git diff-tree --cc $REV
Review difference between commits:
$ git $REV1 $REV2 $ git $REV1..$REV2 $ git $REV1..$REV2 -- $DIR_OR_FILE
Review history with diffs:
$ git log -p $ git log -p $FROM_REV
Review history of merges only:
$ git log --min-parents=2 -p --cc
git does not directly support such feature. Recently hg start tracking changes that pushed to any other repositories (called as public versus draft which is not yet published anywhere). You can emulate it by:
$ git fetch origin $ git log origin/master..master $ git log origin/master.. $ git log origin/master..HEAD $ git log @{u}.. $ git diff origin/master..
Verbose syntax:
$ git log --branches --not --remotes
$ git log --all --graph $ git log --all --graph --oneline $ git log --all --graph --oneline --decorate
Add alias:
[alias] glog = log --all --graph
To edit commit message of last commit:
$ git commit --amend -m "$MSG"
To integrate changes into last commit (-a to avoid antecedent git add ..., --no-edit if you don't like to change commit message, otherwise external editor is opened):
$ git commit -a --amend --no-edit
To edit messages of old commits starting from $REV:
$ git rebase -i $REV
To undo latest commit:
$ git reset HEAD~1
$ git rev-parse --show-toplevel
$ git branch -u upstream/foo $ git branch -u upstream/foo foo $ git branch --set-upstream-to=upstream/foo $ git branch --set-upstream-to=upstream/foo foo
Showing what and how local branches are tracked:
$ git branch -vv $ cat .git/gitconfig
Showing what remote branches tracked:
$ git remote show $remote
If there are no any reset, rebase or merge afterwards the easiest way to recode to pre-rebase state is one of:
$ git rebase --abort $ git reset --hard ORIG_HEAD
Otherwise look to:
$ git reflog
and reset to necessary head:
$ git reset --hard "HEAD@{...}"
git reset --hard is destructive command without backup data.
You may find your previously added data in Git garbage:
$ git fsck --lost-found
look to files inside .git/lost-found directory.
Reviewing git reflog also may help.
$ git reset HEAD^ $ git push --force
Alternative commands may look like:
$ git reset --hard $HASH $ git push -u origin master --force
You can delete remote branch with syntax of appended colon before branch name:
$ git reset HEAD^ $ git push origin :$NAME $ git push origin $NAME
bad changes should be later in graph history then good ones. To use alternative names:
$ git start --term-old=... --term-new=...
Start bisecting with:
$ git bisect start
Mark good and bad revisions:
$ git co vBAD $ make test $ git bisect bad $ git co vGOOD $ make test $ git bisect good
If build/test failed to complete use:
$ git bisect skip
To restore mistakenly marked revisions:
$ git bisect log >$LOG $ git bisect reset $ $EDITOR $LOG $ git bisect replay $LOG
Check patch summary:
git apply --stat my.patch
Detect possible errors during patch application:
git apply --check my.patch
Apply patch to working tree without commit:
git apply my.patch
Commit patch:
git am my.patch
Commit patch by signing you as reviewer:
git am --signoff my.patch
Git uses libcurl for network operation:
$ export GIT_CURL_VERBOSE=1 $ git ...
$ mkdir $REPO $ cd $REPO $ git init $ git add . $ git commit -m "Initial commit" $ git remote add origin https://$USER:$PASS@$HOST/$REPO $ git push -u origin master
$ git show-ref --heads -s
To search string in all or specific files or working copy:
$ git grep $PATT $ git grep -i $PATT -- '*.[ch]'
To search for string in commit messages:
$ git log --grep $PATT $ git log --grep $PATT --all
To search in all history:
$ git log -S$PATT $ git log --pickaxe-regex=$PATT $ git log -G$PATT $ git grep -i PATT $(git rev-list --all) -- '*.[ch]'
Note
-G search occurences in diff chunks, while -S detects changes in match count.
$ git describe $REV
Many projects set tags on branches rather then mainline (for example JS/CSS projects perform build and commit binary/minified files, which unnecessary for mainline history). In this case review simplifiied history by:
$ git log --graph --all --decorate --oneline --simplify-by-decoration
$ git log --tags --simplify-by-decoration --pretty="format:%ci %d"
$ git checkout 'master@{1979-02-26}' $ git checkout 'master@{1979-02-26 18:30:00}'
Create a bundle (a single file with specified Git objects, --all for complete history):
$ git bundle create $REPO.bundle --all
Recreate repository from bundle:
$ git clone $REPO.bundle $REPO_DIR
Note
git init; git bundle unbundle $BUNDLE doesn't recreate refs, you need to use git clone instead.
Or clone without checking out working directory:
$ git clone --mirror $ORIG $DEST
Bundle is a single file, clone creates .git file hierarchy.
Prepare SVN and git utilities:
$ sudo apt-get svn git-core git-svn
Making SVN repo:
$ cd $HOME/tmp $ svnadmin create svn-repo $ svn co file://$HOME/tmp/svn-repo svn-devel $ cd svn-devel $ mkdir tags trunk branches $ svn add * A branches A tags A trunk $ cd trunk/ $ printf "all:\n echo XXX\n" >Makefile $ printf "int main() {return 0;}" >main.c $ svn add * $ cd .. $ svn st A trunk A trunk/main.c A trunk/Makefile A branches A tags $ svn ci -m init Adding branches Adding tags Adding trunk Adding trunk/Makefile Adding trunk/main.c Transmitting file data .. $ svn cp -m v0.0 file://$HOME/tmp/svn/trunk file://$HOME/tmp/svn/tags/v0.0 $ svn cp -m v0.1 file://$HOME/tmp/svn/trunk file://$HOME/tmp/svn/branches/v0.1
Moving SVN changset to git repo:
$ cd $HOME/tmp $ git svn init file://$HOME/tmp/svn git-repo $ ls -a . .. .git $ git svn fetch A trunk/main.c A trunk/Makefile W: +empty_dir: branches W: +empty_dir: tags r1 = 52ccd9882979dd53ec198dbac108783ec660410f (git-svn) A tags/v0.0/main.c A tags/v0.0/Makefile r2 = 8ec8a772bb6f37ace56b3649066dc84e481ed427 (git-svn) M trunk/Makefile r3 = 2c169ff409ed504dd6a092b1e302beb3fd94871e (git-svn) A branches/v0.1/main.c A branches/v0.1/Makefile r4 = e68d76f4ba6beea4b9059c1884c1f38ce10831a7 (git-svn) M trunk/Makefile r5 = cdde63974454b13ac53f2eeb201aa76c49fd875c (git-svn) Checked out HEAD: file:///home/sasha/tmp/svn r5
or (in old git version):
$ git svn clone file://$HOME/tmp/svn git-repo
Making changes in svn:
$ cd $HOME/tmp/svn-devel/trunk $ echo ".PHONY: clean" >>Makefile $ svn ci -m "Added clean to phony." Sending trunk/Makefile Transmitting file data . Committed revision 6.
Making committed in git:
$ cd $HOME/tmp/git-repo/trunk $ echo ".PHONY: all" >>Makefile $ echo "int foo(int x) {return x+x;}" >>main.c $ git status # On branch master # Changed but not updated: # (use "git add <file>..." to update what will be committed) # # modified: Makefile # modified: main.c # no changes added to commit (use "git add" and/or "git commit -a") $ git commit -a -m "Bug fixed." Created commit 222d399: Bug fixed. 2 files changed, 2 insertions(+), 0 deletions(-)
Getting changes from SVN to git:
$ git svn rebase M trunk/Makefile r6 = 8165e9bfb38e9df09a7313d19606ec227629b670 (git-svn) First, rewinding head to replay your work on top of it... Applying Bug fixed. error: patch failed: trunk/Makefile:6 error: trunk/Makefile: patch does not apply Using index info to reconstruct a base tree... Falling back to patching base and 3-way merge... Auto-merged trunk/Makefile CONFLICT (content): Merge conflict in trunk/Makefile Failed to merge in the changes. Patch failed at 0001. When you have resolved this problem run "git rebase --continue". If you would prefer to skip this patch, instead run "git rebase --skip". To restore the original branch and stop rebasing run "git rebase --abort". rebase refs/remotes/git-svn: command returned error: 1 $ git add Makefile $ git rebase --continue Applying Bug fixed.
and return all from git to SVN:
$ git svn dcommit Committing to file:///home/sasha/tmp/svn ... M trunk/Makefile M trunk/main.c Committed r7 M trunk/main.c M trunk/Makefile r7 = 68e782c8d06635f2db4dd69b9ca8599f99da22e2 (git-svn) No changes between current HEAD and refs/remotes/git-svn Resetting to the latest refs/remotes/git-svn
See what going to SVN repo:
$ cd $HOME/tmp/svn-devel/trunk $ svn diff -r BASE:HEAD Index: Makefile =================================================================== --- Makefile (working copy) +++ Makefile (revision 7) @@ -6,4 +6,4 @@ .o: .c $(CC) $(CFLAGS) -c -o $@ $< -.PHONY: clean +.PHONY: all clean Index: main.c =================================================================== --- main.c (working copy) +++ main.c (revision 7) @@ -2,3 +2,4 @@ { return 0; } +int foo(int x) {return x+x;} $ svn up U Makefile U main.c Updated to revision 7.
Get latest changes from SVN and update Git repo state:
$ git svn fetch $ git svn rebase
gitk - The git repository browser. See gitk(1).
Installing:
$ sudo apt-get instal gitk
Using:
$ cd /path/to/git-repo $ gitk