Git
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
- Website: http://git-scm.com/
- Download: http://git-scm.com/downloads
Git Global Setup
git config --global user.name "Your Name Here" git config --global user.email [email protected] git config --global core.editor "vim" git config --global color.branch auto git config --global color.diff auto git config --global color.interactive auto git config --global color.status auto
Git Commands
Common Git Commands
To download a new git repository
(Public access)
git clone http://git.example.com/folder/project.git
Update an exciting repository
(From within the projects folder)
git pull
Comment a change
git comment file.txt
To Revert a comment
git revert ce963c9db00c25b3c1e6add1fe6032aef61a5bed
Commit
Modify the last commit
git commit --amend
Patches
Creating a patch
To create a patch file of the last commit
git format-patch -1 gzip 0001-name_of_patch_file.patch
Patching a file or directory
gzip -dc 0001-name_of_patch_file.patch.gz |git apply
Branching
Creating a new branch
git branch <branch>
or to create a branch and switch to it
git checkout -b <branch>
Pulling changes from branches
git checkout <branch_committing_to>
Now that your in the branch you want to add the changes to, run:
git pull . <branch_committing_from>
Changing to a different branch
git checkout <branch>
Deleting a branch
git branch -d <branch>
Deleting a remote branch
git push origin :<branch>
Pushing a branch to github
git push <remote_repository_name> <branch_name>
So that would be...
git push origin <branch>
Display branches on github
git remote show origin
Pulling a branch from github
git checkout --track -b <name_of_local_branch> origin/<name_of_remote_branch>
Tagging
Tagging a branch
git tag -a -m "tagging version 1.0" 1.0
Pushing the tag to github
git push --tags
Deleting a tag
git tag -d 1.0
Removing a deleted tag from github
git push origin :refs/tags/1.0
Submodules
To install existing submodules
git pull git submodule init git submodule update
To add a new submodule to a project
git submodule add <remote-host>:<project.git> <project.git>
So if you are adding project "program" from the example git server you will run
git submodule add git://example.com/program.git program
To Update an existing submodule
cd <submodule> git pull origin master cd .. git commit -a -m "Updated submodule." git push
Import tags from SVN into an existing git repo
git gc for c in `cat .git/packed-refs |grep remotes |grep tags |grep -v '@' |sed 's/\// /g' |awk '{print $5}'` do d=`git tag |grep -x "$c" |wc -l` if [ "$d" == "0" ]; then echo "Creating new tag, $c" git tag -a $c -m "Converting SVN tag to GIT tag" remotes/tags/$c sleep 3 fi done
Mirroring a Repository
To Mirror a remote repository first you must check out the repository as so
git clone --mirror git://example.com/example_repo.git
After you have the repository correctly checked out, you may update it via the fetch command.
cd example_repo git fetch
Installing Git from Source
First install all needed dependence:
yum install gcc perl-devel perl perl-DBD-Multi zlib-devel zlib \ openssh-server openssh libcurl expat expat-devel xinetd
Now Download Git via a tarball:
mkdir -p /var/src cd /var/src rm -rf git-git* wget --no-check-certificate https://github.com/git/git/tarball/master tar -xzf git-git* cd git-git*
Or if you already have git installed, via git it's self:
mkdir -p /var/src cd /var/src git clone git://git.kernel.org/pub/scm/git/git.git cd git
Now compile the install.
make configure && ./configure --prefix=/usr && make && make install
or
cd /var/src && rm -rf git && git clone /home/git/public/mirror/git.git && cd git && \ make configure && ./configure --prefix=/usr && make && make install && \ make GITWEB_PROJECTROOT="/home/git/secure" GITWEB_HOME_LINK_STR="secure" && \ rm -rf /var/www/code.mattrude.com/secure/gitweb.cgi && \ cp gitweb/gitweb.cgi /var/www/code.mattrude.com/secure/gitweb.cgi && echo $?
Sending emails on commits
Git's Native eMail Notifier
From the repository you wish to send email on commits.
cd .git/hooks mv post-receive post-receive.bkp ln -s /usr/share/git-core/contrib/hooks/post-receive-email post-receive git config hooks.mailinglist "[email protected]" git config hooks.emailprefix "[SUBJECT PREFIX] " # note the trailing space
Git Commit Notifier
This 'plugin' will allow you to send an email every time a commit is committed to the repository. You may use this on the central repository to keep everyone following the project up to date.
- The source may also be downloaded at http://github.com/bitboxer/git-commit-notifier
To use this plugin, you first need to compile the script, then add the config information to each repository you wish to use it on.
To Install Git Commit Notifier from gem
On Fedora 12 you first need to install Ruby and a few other dependencies. After you download the needed dependencies, you may compile the script.
yum install ruby rubygems hpricot rubygem-hpricott gem install git-commit-notifier
To Install Git Commit Notifier from github
yum -y install ruby rubygems rubygem-nokogiri-doc libxml2-devel libxslt-devel ruby-devel
mkdir -p /var/src cd /var/src/ git clone git://github.com/bitboxer/git-commit-notifier.git cd git-commit-notifier gem build git-commit-notifier.gemspec gem install git-commit-notifier-0.??.?.gem
To Configure Git Commit Notifier
In your repository's .git/hooks folder or if it's a "bare" repository, just the hooks folder. Create a file named "post-receive" with the following content.
#!/bin/sh git-commit-notifier ../git-commit-notifier.yml
Once you have saved the file, you need to make it executable.
chmod 775 post-receive
After you have made the hook executable, check up one directory to the repository's .git directory. From here you need to create and modify your git-commit-notifier's config file. Start out by creating a file named "git-commit-notifier.yml", and copy the below config to it.
Git Commit Notifier Config File
# The recipient for the commit: mailinglist: [email protected] # set to true if you want to ignore empty merge messages ignore_merge: false # Optional parameter for the subject-line of the mail # emailprefix: GIT # Decorate files with link to a webview. Possible values: none or gitweb link_files: none # select the delivery method: smtp or sendmail delivery_method: sendmail # settings for the smtp server smtp_server: address: localhost port: 25 domain: localhost user_name: user@localhost password: password authentication: plain enable_tls: false # settings for sendmail sendmail_options: location: /usr/sbin/sendmail arguments: -i -t # If link_files is set to "gitweb", you need to configure the path to your gitweb # instance and the project name. gitweb: path: http://developerserver/path_to_gitweb project: test.git
Add all remote branches
for b in `git remote show origin |grep tracked |awk '{print $1}'` do LOCALBRANCH=`git branch |sed 's/* //g' |sed 's/ //g' |grep $b` if [ "$LOCALBRANCH" != "$b" ]; then git branch -t $b origin/$b fi done
Creating an unattached branch with no history
From inside your git repository, after you have committed all you changes, run:
git symbolic-ref HEAD refs/heads/name-of-new-branch rm .git/index git clean -fdx
You will now have an empty directory waiting for your first commit.
So if your creating a new branch for github pages for example, you would run:
git symbolic-ref HEAD refs/heads/gh-pages rm -f .git/index git clean -fdx
And your ready to start creating your page.
Allow remote pushes to a checked out repository
In the remote repository you are planing on pushing to, run the following:
git config receive.denycurrentbranch ignore
Then download the File:Post-update.zip and unzip it. Now copy this file to your .git/hooks/ folder and make it executable.
wget http://wiki.mattrude.com/images/d/de/Post-update.zip unzip Post-update.zip rm -rf Post-update.zip chmod 775 post-update mv post-update .git/hooks/post-update
You should now be able to remotely push to this repository without errors.
Creating a new user for git secure remote pushing
adduser -b /home/git -g git -m -s /usr/bin/git-shell kelsey -p
mkdir /home/git/kelsey/.ssh ssh-keygen -n kelsey -t dsa -f kelsey/.ssh/id_dsa
chown -R kelsey:kelsey /home/git/kelsey chmod -R u=rwX,go-rwx /home/git/kelsey/.ssh chmod +rw /home/git/kelsey/.ssh/id_dsa.pub
Creating a Secure Git Remote Server
- On the Server
Create the git repo on the server
mkdir name-of-git-repo.git cd name-of-git-repo.git git init --bare
Create the git repo to import into the server
git init touch README git add README git commit -m 'first commit' git remote add origin git@REMOTE_SERVER:name-of-git-repo.git git push origin master
- http://blog.commonthread.com/2008/4/14/setting-up-a-git-server
- Git servers typically listen on TCP port 9418.[1]
Installing git-up
gem install git-up
Configure per user rights for a Secure Git Remote Server
I use something a bit simpler, all you need is to setup three files, the authorized_keys file, the gitsecurity.rb file and a permissions file gitpermissions. For simplicity they can all go in the git accounts .ssh folder. (Basic unix admin skills required to understand herein)
The gitpermissions file looks like this, and should be fairly self explanitory:
repo1.git|jane|rw repo1.git|james|r repo2.git|bob|rw
The autorized_keys file looks something like this:
command="/home/git/.ssh/gitsecurity.rb jacob",no-port-forwarding,no-X11-forwarding,no-agent-forwarding, \ no-pty ssh-rsa rFaivBw.....5Rws jacob command="/home/git/.ssh/gitsecurity.rb bob",no-port-forwarding,no-X11-forwarding,no-agent-forwarding, \ no-pty ssh-rsa rFaivBw.....5Rws bob
Finally the gitsecurity.rb script, just copy and paste it:
#!/usr/bin/ruby class GitPermission attr_accessor :username; attr_accessor :repository; attr_accessor :read; attr_accessor :write; def initialize(line) bits = line.split('|'); if(bits.length!=3) $stderr.puts "Invalid configuration file" Process.exit(4) end @repository = bits[0] @username = bits[1] @read = bits[2].include?("r") @write = bits[2].include?("w") end end if(!ENV.has_key?("SSH_ORIGINAL_COMMAND")) $stderr.puts "SSH not allowed to the git account." Process.exit(1); end command = ENV["SSH_ORIGINAL_COMMAND"]; if(!ARGV.length == 1) $stderr.puts "Authorised keys file misconfigured, username not specified correctly." Process.exit(1); end if(!ARGV[0].match(/^[A-Za-z0-9]+$/)) $stderr.puts "Authorised keys file misconfigured, username contains invalid characters: "+ARGV[0]; Process.exit(1); end username = ARGV[0] if(!command.match(/git[ -]upload-pack /) && !command.match(/^git[ -]receive-pack /)) $stderr.puts "Only git commands are allowed." Process.exit(2); end repository = command[(command.index(' ')+1)..-1] if(!repository.match(/'.*'/)) $stderr.puts "Repository parameter incorrect." Process.exit(2); end repository = repository[1,repository.length-2] begin file = File.new("/Users/git/.ssh/gitpermissions", "r") while (line = file.gets) p = GitPermission.new(line); if(p.repository == repository && p.username == username) if((p.write == true || (p.read == true && command.match(/^git[ -]upload-pack/))) ) exec "/usr/local/git/bin/" + command Process.exit(0); end end end file.close rescue => err $stderr.puts "Problem with server configuration: #{err}" Process.exit(4) end $stderr.puts "You do not have permission to complete this operation" Process.exit(5)
Importing a SVN repo into git
To import a svn repo create a new git repo and run
git svn clone http://svn.foo.com/svn/project/ project -s
Then once your done, repack it.
git gc project/
SVN Branches
If you wish to also map your branches, you may run something like the following, note how were using awk to see only what we want to see.
for a in `cat .git/packed-refs |grep remotes |grep -v pack-refs |grep -v tags |grep -v trunk \ |grep -v '@'|awk '{print $2}'` do b=`echo "$a" |sed 's/\// /g' |awk '{print $3}'` git branch -t $b $a done
SVN Tags
From a checked out SVN directory, the following will give you a list of all the users in the SVN log. You will still need to updated this list before you may use it.
for a in `cat .git/packed-refs |grep remotes |grep tags |grep -v '@' |awk '{print $2}'` do b=`echo "$a" |sed 's/\// /g' |awk '{print $4}'` echo "creating tag $b" git tag -a $b -m "Converting SVN tag to GIT tag" $a sleep 5 done
SVN Authors list
#!/usr/bin/env bash authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq) for author in ${authors}; do echo "${author} = ${author} <USER@DOMAIN>"; done
Once you have your list built, need to add it to your .git config. I store my authors file in the .git directory.
[svn] authorsfile = .git/authors
GIT/SVN Notes
- http://tsunanet.blogspot.com/2007/07/learning-git-svn-in-5min.html
- http://djwonk.com/blog/2008/05/09/cleanly-import-svn-repository-into-git/
Git Links
- http://github.com/guides/home
- http://whygitisbetterthanx.com
- http://blog.jrock.us/articles/Git%20merging%20by%20example.pod