Pro Git professional version control
User manual http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
Why you should choose git as your DVCS: http://0pointer.de/blog/projects/on-version-control-systems.html
Git magic: http://www-cs-students.stanford.edu/~blynn/gitmagic/
Screencasts of how to do stuff in git
Git for Subversion users: http://git.or.cz/course/svn.html
Git for computer scientists: http://eagain.net/articles/git-for-computer-scientists/
Branching and merging with git: http://lwn.net/Articles/210045/
Keith Packard's - Repository formats matter
Merge-level conflict resolution: Linus style http://www.ussg.iu.edu/hypermail/linux/kernel/0802.1/2406.html
Mostly taken from the git user manual. /usr/share/doc/git-core-1.5.2.2/user-manual.txt
One way to submit changes to a project is to tell the maintainer of that project to pull the changes from your repository using git-pull.
A common way to do this is to maintain a separate public repository (usually on a different host) for others to pull changes from. This is usually more convenient, and allows you to cleanly separate private work in progress from publicly visible work.
You will continue to do your day-to-day work in your personal repository, but periodically "push" changes from your personal repository into your public repository, allowing other developers to pull from that repository. So the flow of changes, in a situation where there is one other developer with a public repository, looks like this:
you push your personal repo ------------------> your public repo ^ | | | | you pull | they pull | | | | | they push V their public repo <------------------- their repo
To setup a new repository, do the following.
$ cd /srv/git $ mkdir <new-repository>.git $ cd <new-repository>.git $ git init --bare $ vi description $ vi config
add the following stanza to deny non fast-forward pushes
[receive] denyNonFastForwards = true
add the following stanza
[gitweb] owner = Your Name
If you want this repository to be served via git-daemon:
$ touch git-daemon-export-ok
Back on your workstation. If you don't have a repository, create one.
$ cd project $ git init $ git add . $ git commit -m "Initial Commit"
Now's the time to make sure your details are correct.
You can set your name and email address globally or on a per repository basis.
$ git config --global user.name "Your Name" $ git config --global user.email you@example.com
Will set them globally. To set them just for the current repository, strip out the --global
With an existing repository, make sure your on the 'master' branch.
$ git checkout master
Create a remote link with the repository you created above.
$ git remote add origin ssh://git.example.com/srv/git/new-repository.git
Push your repository up
$ git push -u origin master
If you have other branches you wish to push
$ git push origin <branch>
If you have tags you wish to push, you can push them all in one go
$ git push origin --tags
Individual tags can be pushed as
$ git push origin <tag>
Largely taken from http://progit.org/book/ch8-2.html with some modifications.
Clone the SVN repository.
$ git svn clone https://svn.example.com/repos/repository \ --authors-file=users.txt --no-metadata -s my_project
or
$ git svn clone https://svn.example.com/repos/repository/branches/somebranch \ --authors-file=users.txt --no-metadata my_project
Do some cleanups
$ cp -rf .git/refs/remotes/tags/* .git/refs/tags/ $ rm -rf .git/refs/remotes/tags $ cp -rf .git/refs/remotes/* .git/refs/heads/ $ rm -rf .git/refs/remotes $ rm -rf .git/svn
Delete any branches it left around from the migration. e.g trunk, git-svn
$ git branch -d trunk
Edit .git/config and remove the svn stanzas.
Set your details if needed.
$ git config user.name "Your Name" $ git config user.email you@example.com
Garbage collect the repository
$ git gc
Connect to the remote repository
$ git remote add origin ssh://git.example.com/srv/git/repository.git
Push all branches
$ git push origin --all
Push all tags
$ git push origin --tags
Following the steps from here.
We need to get the hg-fast-exporter.
$ git clone git://repo.or.cz/fast-export.git
Create the new git repository
$ mkdir repository_git
Clone the Mercurial repository
$ hg clone ssh://hg.example.com//srv/hg/repository
Change into the new git repository and initialise it
$ cd repository_git $ git init
Now to run the export script
$ ../fast-export/hg-fast-export.sh -r ../<hg repository> -A ../git-author-mapping.txt
Checkout the trunk or HEAD branch
$ git checkout trunk or HEAD
Use git filter-branch to rewrite authorships if necessary.
Make a master branch
$ git checkout -b master
Delete the other branch
$ git branch -d trunk or HEAD
Set your Name and email address if required.
$ git config user.name "Your Name" $ git config user.email you@example.com
Garbage collect the repository
$ git gc
Connect to the remote repository
$ git remote add origin ssh://git.example.com/srv/git/repository.git
Push all branches
$ git push origin --all
Push all tags
$ git push origin --tags
As gleamed from
Problem:
You have a repository that has a foo subdirectory and you want to make that its own repository with its history intact.
repository/ bar/ baz/ foo/
You want foo/ to become a repository.
There are two ways of doing this. With Git versions >= 1.7.11 you can do this$ mkdir new_repository $ cd new_repository $ git init --bare $ cd ../current_repository $ git subtree split --prefix=foo -b foo $ git push ../new_repository foo:master $ git branch -D foo $ cd ../new_repository $ mkdir .git $ mv * .git/ $ vim .git/config # set bare = false $ git reset --hard
For older versions of Git, you should do this
Firstly make a clone of the repository.
$ git clone --no-hardlinks repository new-repository
Then make foo/ the new HEAD
$ cd new-repository $ git filter-branch --subdirectory-filter foo HEAD -- --all $ git reset --hard $ git gc --aggressive $ git prune
You should then remove the old origin
$ git remote rm origin
You can then set this up as a new central repository as shown above.
Particularly useful when migrating mercurial repositories to git, where what should be a branch is in a separate repository.
This is actually pretty simple. Once you have your git repositories, it boils down to:-
$ mkdir combined-repo $ cd combined-repo $ git init
For each repository you want to make a branch
$ git remote add <repo> </path/to/repo> $ git fetch <repo> $ git checkout -b <repo> <repo/branch>
Kind of the reverse of the above.
$ mkdir split-repo $ cd split-repo $ git init $ git remote add <repo> </path/to/repo> $ git fetch <repo> $ git checkout -b master <repo/branch>
If you have checked out a git repository with more branches than just master. Then these additional branches won't show up by default.
List remote branches.
$ git branch -r
Switch to a remote branch keeping track of changes. This means running git-pull will automatically merge in changes in the upstream <remote branch> into your local branch just like origin/master --> master.
$ git checkout --track origin/<remote name>
or to give the branch a different name
$ git checkout --track -b <local name> origin/<remote name>
$ git config --global user.name "Your Name" $ git config --global user.email email@address
That sets those globally, you can set it per repository by dropping the --global
Have the current git branch displayed in your shell prompt when your inside a git repository.
export PS1="[\u@\h \W\$(git branch 2> /dev/null | grep -e '\* ' | sed 's/^..\(.*\)/{\1}/')]\$ "
If you have committed local changes, then git-pull will create a spurious "Merge" commit, which will pollute the change list when you later push upstream. To avoid this, do these two commands:
$ git fetch $ git rebase origin
Instead of merging, this attempts to insert the changes you pull from the origin repository before your local changes, avoiding the merge message.
git status says:
$ git status # On branch master # Your branch is ahead of 'origin/master' by 2 commits.
You want to git push only one of those commits to the public repo. Here’s how:
First use git log to get the commit hash of the commit you want to push. Then:
$ git push origin <thelonghash>:master
$ git pull https://github.com/jasonblewis/xlander masterThis would merge the changes from the specified repository/branch into your current branch. However it may often be useful to inspect the changes locally before actually applying them. To do this you can
$ git fetch https://github.com/jasonblewis/xlander masterInspect the changes like
$ git diff ..FETCH_HEADthen merge the changes with
$ git merge FETCH_HEAD
http://gitolite.com/detached-head.html
$ git push origin :branchname
Where branchname is the branch you want to delete. This basically says push up an empty/non-existent branch to branchname
http://book.git-scm.com/5_creating_new_empty_branches.html
$ git symbolic-ref HEAD refs/heads/NEWBRANCH $ rm .git/index $ git clean -fdx <do work> $ git add your files $ git commit -m 'Initial commit'
Set one of these environment variables to vim
GIT_EDITOR VISUAL EDITOR
in your ~/.bashrc or equivalent.
Or set the core.editor git config option to vim, i.e
$ git config --global core.editor vim
When using vim as your commit message editor, it will remember its last position in the commit message file, .git/COMMIT_EDITMSG. Put the following in your ~/.vimrc to make vim always start at the origin for commit messages.
autocmd FileType gitcommit call setpos('.', [0, 1, 1, 0])
Use the width arguments(s) to --stat.
--stat=<width>[,<name-width>]
The first width is the terminal width, the second is the width allowed for the filename
e.g
$ git diff --stat=160,140
With C code, sometimes git diff output will show a label name instead of the function name for a hunk, e.g
@@ -2749,6 +2726,8 @@ out: out2: free_vars(qvars); + free_avars(); + free_u_files(); gettimeofday(&etv, NULL); d_fprintf(access_log, "Got request from %s for %s (%s), %f secs\n", env_vars.http_x_forwarded_for,
By adding the following (from Peter Zijlstra) to your ~/.gitconfig or <project>/.git/config
[diff "default"] xfuncname = "^[[:alpha:]$_].*[^:]$"
You will now get:
@@ -2749,6 +2726,8 @@ void handle_request(void) out2: free_vars(qvars); + free_avars(); + free_u_files(); gettimeofday(&etv, NULL); d_fprintf(access_log, "Got request from %s for %s (%s), %f secs\n", env_vars.http_x_forwarded_for,This can also be achieved using gitattributes by adding
*.c diff=cpp *.h diff=cppto a .gitattributes file
If you've made two or more commits and you need to edit the first one, you can't do that with git rebase -i
Instead, it's a little more involved (from stackoverflow)
Note: Of course, you should only do this on a branch that has never been pulled by anyone... I.e a project that you haven't pushed anywhere and you want to clean up before you do.
# tag the old root, "git rev-list ..." will return the hash of first commit git tag root `git rev-list HEAD | tail -1` # switch to a new branch pointing at the first commit git checkout -b new-root root # make any edits and then commit them with: git commit --amend # check out the previous branch (i.e. master) git checkout @{-1} # replace old root with amended version git rebase --onto new-root root # you might encounter merge conflicts, fix any conflicts and continue with: # git rebase --continue # delete the branch "new-root" git branch -d new-root # delete the tag "root" git tag -d root
$ git reset HEAD^
$ git show <treeish>:<file>
$ git branch --contains <commit>
Source: (http://lwn.net/Articles/290428/)
http://lwn.net/Articles/291302/
http://lwn.net/Articles/291303/
http://lwn.net/Articles/291304/