GIT
Links
- git Homepage
- git Wiki
- git Wikipedia article
- git on kernel.org
- Kernel hackers guide to git
- Talk about git from Linus Torvalds
- IRC Channel #git on freenode
- archive of the git mailing list
Basic usage
- this site is heavily inspired by a tutorial introduction to git
- git-gui and gitk --all are very helpful to understand what is happening
- See the paragraph SPECIFYING REVISIONS in git-rev-parse(1) for possibilities to address a revision in git
Start a new repository
Introduce yourself to git
git config --global user.email "foo@example.com"
Either create a new, empty folder ...
cd project
git init # git init-db
... or use an existing one
cd project
git init # git init-db
Note: gitk won't work in new git repositories before your first commit. Until then the following error will occur:
while executing
"close $refd"
(procedure "readrefs" line 47)
invoked from within
"readrefs"
(file "/usr/bin/gitk" line 6370)
Add all files to the repository and commit.
git add--interactive
git commit
Adopt changes to local repository
What has changed?
git diff path/to/file
In contrast to Subversion you have to tell git which before each commit which of the tracked files should be considered. This is also achieved via git-add
You can also add them via git-gui in a more convenient way.
After you added those files with git-add they are no longer shown by git-diff. But you can still see what changes will be committed
git diff --cached path/to/file
Now really add changes to your local repository
git commit -m "* Bla bla" path/to/new/file
Another way is to tell git to commit all tracked and changed files without calling git-add on each file
If you made a mistake in the last commit you can still change it
Another way
...
git commit -c ORIG_HEAD
Show modifications
git diff --color --color-words
git diff --ignore-space-at-eol --ignore-space-change
git diff -- path/to/file
git diff HEAD -- path/to/file
git diff HEAD^ -- path/to/file
git diff HEAD^^ -- path/to/file
git diff HEAD^^ HEAD^ -- path/to/file
git diff 68fcc0 ef6274 -- path/to/file
git diff HEAD ef6274 -- path/to/file
git diff ef6274 ef6274^ -- path/to/file
git diff master experimental -- path/to/file
git diff master origin/master -- path/to/file
git whatchanged 68fcc0 ef6274 -- path/to/file
git diff --name-only 68fcc0 ef6274
git status
git status -s
git log
You can also filter the output of diff, e.g. to show only deleted files, only modified files, ...
git diff --diff-filter=M --name-only
Remove files from the work area and the repository
Remove files only from the repository
Show who changed what in a file
Exclude files from the repository
There are two possibilities to exclude files from the repository
- You can exclude them via .git/info/exclude. However this will only affect your local repository.
foo.txt
# (2)
*.html
# (3)
!foo.html
# (4)
*.[oa]
- You can create files named .gitignore in any of your folders to exclude files. This will affect files this folder and all of its subfolders. This has the advantage that the .gitignores can be added to the repository and shared among different repositories. If you like to exclude all files of a folder with this method don't forget to exclude the .gitignore from the exclusion.
!.gitignore
Additional information can be found in gitignore(5).
Patches
Save changes of repository in files in the given folder. These patches can be easily send via mail to propagate changes
git format-patch --numbered --thread -o /tmp/mypatches/ -2
Save to diff between current branch and the branch origin into a patch
Get all patches which are in the given mbox and apply them to the current branch
git format-patch -k --stdout HEAD^^ HEAD | git am --3way --keep
Send patches directly via mail (if you skip recipient or sender it will be extracted from the repository automatically)
Apply a patch
git apply foo.patch
git apply --reject foo.patch
git apply --reverse foo.patch
Apply a given commit to the current branch
Maintenance
Speed up repository with compression (do this from time to time)
Check repository for bugs
If this prints lots of rows starting with dangling ... do this
Get other versions of a file in the repository
View other versions of a given file
git show HEAD:path/to/file
git show HEAD^:path/to/file
git show HEAD^^:path/to/file
git show HEAD~3:path/to/file
Restore older versions of a given file
it checkout filename
Tags
Create a Tag
Branches
Create branch
git checkout -b experimental
Show all branches
git branch -r
git branch -a
Which branch is current
Switch branch
Switch back
Undo all local modifications
Revert local changes
Merge all changes from branch experimental into the current branch
Delete branch
Merge two branch back together The current branch will get the changes of the branch experimental so both will be equal
Merge a conflict during merging Either edit the files manually with an editor, or chose like this if you want to keep your version and overwrite what the others did or keep what the others did and throw away your changes.
git checkout --theirs the/file/with/problems.java
Whatever you did at the end you need
git commit
Continue merge after conflict
rebase
Assume you have the following branches
/
D-->E-->F-->G master
and you want that the foo branch
starts at the head of the master branch
/
D-->E-->F-->G master
If you are already in the foo branch it's enough to issue
to move the current branch on the head of the master branch.
Otherwise the following command
moves regardless of the current branch the foo branch on top of the head of the master branch.
Finally you can even move a given sub branch onto the head of a another branch. Assume you have
/
C-->D-->E foo
/
A-->B master
the the following command
will achieve this result
/
A-->B master
F-->G-->H bar
Avoid git merge commits with rebasing
Branch strategies
Teamwork
Suppose Alice has a git repository in /home/alice/project, now Bob wants to help Alice and also work on the project. With the following command he'll gets a clone of the repository in the folder myrepo.
After you cloned the remote repository you'll find one branch, master
* master
However, the remote repository might have more than one branch. Luckily, they are already here for you
git branch -a
If you want to have a first look into one of those branches, you can switch to them right away
If you like to use this remote branch also in your repository, create a local branch for it and mark it to track changes
If Alice commits new changes into her repository Bod can pull those changes into his repository
If Bob has local, not yet commited changes he can park those changes for a moment, pull, and then try to apply the parked changes again
git pull
git stash pop
If it Bob who did commits into his repository, he can either push those changes into Alice's repository, or she can pull them by herself.
Updating 123456..abcdefgh
To see the changes you just got (replace with the ids you saw in the pull)
git diff 123456..abcdefgh
If Bob created new branches he can push the like this into Alice's repository
He can also push the single new branch MyNewBranch to the remote repository origin
You can also fetch the changes first without an immediate merge
How to review those changes
git diff master...origin/master
git diff master origin/master
git log origin/master ^master
And then merge the fetched changes (as git pull would have done
It is even possible to add references to more than one repository. Add a new one like this
git remote add origin2 git://foo/bar
git remote add origin3 ssh://user@foo.bar/~/foobar.git
Show remote repositories, get URL of repository you cloned from / push to
git remote show origin
Remove remote repository
Your own git server
There are several possible protocols available
- git-deamon
Fast, but read only
- http
Slow, but no problems with firewalls / proxies. Normally also only read only.
- ssh
Read and write access
- Local filesystem
Fast, read and write access
See also HOWTO setup a git repository.
Example for git deamon server
Server, with a given folder where the repository should lie, e.g. /var/cache/git
Client, we already have a repository (e.g. /home/foo/bar) and like to export it to the server
Enable export on repository
Copy folder to server
Now you should be able to access the repository via git
Example for git ssh server
We also clone a repository (or use an existing one)
We create a new user, e.g. git which will be used to log in via ssh (or use existing users). If you use an extra user, you might consider to restrict his shell to /usr/bin/git-shell (/etc/passwd) You might use a different port for the ssh deamon for the git usage
Subversion and git
One time import from a subversion repository into a git repository
This will expect that you followed the subversion recommendation to have the following repository structure
branches/foo
branches/bar
branches/...
but with appropriate command line parameters you can import other structures as well
In one of my projects there was no trunk folder at all. As of now (August 2007) git-svnimport can not import such repositories. However there is a small patch for git-svnimport and empty trunk folder. In my project with commit 325 a trunk folder was created and everything was moved into it. With a git-importsvn version which can handle empty trunk folders the import worked in two steps
git svnimport -o tmp1 -s 325 -T 'trunk' http://example.com/myproject
git checkout tmp1
git rebase master
However there was manual intervention required to merge both parts.
If you like to use git and subversion in parallel you might be interested in git-svn
git undo
If something went wrong with your git repository you can try to undo the last git actions
24f34f2... HEAD@{0}: pull : Fast forward
68fh47g... HEAD@{1}: checkout: moving to master
90cdrt3... HEAD@{2}: pull : Fast forward
62dgs35... HEAD@{3}: rebase: ...
# git reset --hard HEAD@{1}
Find erros with bisec
If the current project has a bug delcare it as bad and explain which is the last version which worked
git bisect bad
git bisect good v2.6.13-rc2
This will give you a version between the broken and the working version. Try it and declare it as bad or good.
until you find the modification which causes it. To quit bisec and get back the latest version
Kernel
Get a copy of the (complete!) kernel repository from Linus
Note that there will be no tags for the stable kernel in it. So you may decide to use the stable Kernel git instead
which has tags for the stable kernel.
List all available tags
If you already have downloaded the Linus git you can use it as a source for the stable one (untested, needs git 1.3)
Show difference between two versions for the file MAKEFILE
Create a new branch, and get version with a specific tag into it (does not require network as you have complete repository). With this command you can get a specific kernel out of the git
git pull
git checkout -f -b my-new-branch tags/v2.6.16.19