Version 2.8
Copyright © 2009 - 2010 Lars Vogel
29.08.2010
| Revision History | ||
|---|---|---|
| Revision 0.1 | 13.09.2009 | Lars Vogel |
| Created | ||
| Revision 0.2 - 2.0 | 21.11.2009 - 29.08.2010 | Lars Vogel |
| bug fixes and improvements | ||
Table of Contents
Git is a distributed version control system (dvcs) written in C. A version control system allows that you can create a history for a collection of files with the possibility to revert them to another state. These collection of files is usually called "source code". In a distributed version control system everyone has a complete copy of the source code (including the complete history of the source code) and can perform version control operations against this local copy. The usage of a dvcs does not require a central code repository.
Git supports branching, e.g. you can have different versions of your source code, for example if you want to develop a new feature you may open a branch in your source code and make the changes in this branch without affecting the main line of your code. Git keeps track of all versions. If you have done some changes which should be keept in the version control system you mark them as relevant (staging) and then you commit these changes to git.
Git allows local commits to your repository and you can later merge these changes with remote repositories. If you want to get the source code from a repository you clone the repository. Once the repository is cloned it is possible to commit changes to the clone. Owners of repositories can merge changes via push (transfer changes to a remote repository) or via pull (getting changes from a remote repository).
Git can be used from the command line; this approach will be described in this tutorial. You also find graphical tools for example EGit for the Eclipse IDE .
Table 1. Git Terminology
| Term | Definition |
|---|---|
| Repository | A repository contains the history, the different versions over time and all different branches and tags. In Git each copy of the repository is again a complete repository. The repository allows to retrieve revisions into your working copy. |
| Branches and Tags | A Git repository contains always all branches and tags. One of the branches is the default (normally named master). The user checkout a version branch to work in this branch, this is called the "working copy". |
| Commit | You commit your changes into a repository. This is create a new revision which can be later retrieved, for example if you want to see the source code of an older version. Each commit contains the author and commiter fields which identifies how create the change and who commited it. |
| URL | An URL in Git determines the location of the repository. |
| Revision | Represents a version of the source code. Git identifies revisions with SHA1 ids. SHA1 ids are 160-bit long and are represented in hexadecimal. The latest version can be address via "HEAD", the version before that via "HEAD~1" and so on. |
Git requires you to mark changes explicit to be relevant for committing them to the repository. For example if you what to have a file or changes in a file being relevant for the next change you have to add them to the so called "staging index" via git "add file". For files which were already committed once you can use the the "-a" flag during a commit. The staging index will be a complete snapshot of the changes.
On Ubuntu you can install the Git command line tool via "sudo apt-get install git-core". A windows version of git can be found on the msysgit Project site
Configure your user and your email for git via the following command.
# Config the user which will be used by git # Of course you should use your name git config --global user.name "Lars Vogel" # Same for the email addess git config --global user.email "Lars.Vogel@gmail.com" # Set default so that always all changes are pushed to the repository git config --global push.default "matching"
To query your git settings via:
git config --list
You can tell git to ignore files via the ".gitignore" file. This file can be in any directory and can contain pattern for files. For example you can tell git to ignore the directory "bin" via the following ".gitignore" in the main directory.
bin
The following will guide you though a typical Git workflow. You will create a few files, create a local Git repository and commit your file into this repository. Afterwards you clone the repository and push and pull some changes between the repositories.
Open a command line / shell for the operations. The comments before the commands try to explain the action your are performing.
Create some content which we later put under version control.
#Switch to home cd ~/ # create a directory mkdir repo01.git # switch into it cd repo01.git # create a new directory mkdir datafiles # Create a few files touch test01 touch test02 touch test03 touch datafiles/data.txt # put a little text into the first file ls >test01
Create a Git repository, add the files to the repository and commit your changes.
# Initialize the local Git repository git init # Add all (files and directory) to the Git repository git add . # Make a commit of your file to the local repository git commit -m "Initial commit" # Show the log file git log
Every git repository is stored in the .git folder of the root directory. This directory contains in the .git/config the local configuration for the repository and the complete history of the repo.
Make some changes to the file, see the differences and commit them again to the repository.
# Make some changes in the file echo "This is a change" > test01 echo "and this is another change" > test02 # Check the changes via the diff command git diff # commit the changes, -a will commit changes for modified files # but will not add automatically new files git commit -a -m "These are new changes - typo in the commit message"
In the above example the commit message was incorrect. You can change the last commit message via the --amend parameter.
git commit --amend -m "These are new changes"
We will now create a remote git repository. Git allows to store this remote repository either on the network or locally. For simplification we will a local remote git repository. A standard git repository is different from a remote git repository. A standard git repository contains the source code and the git repository. You can work directly in this directory, e.g. the repo contains the working copy for all files Remote repositories do not contain working copies of the files, they only contain repository files. To create such are repository such the "--bare" flag.
# Switch to first repository cd ~/repo01.git # git clone --bare . ../remote-repository.git # Check the content, is be equal to the .git directory in repo01.git ls ~//remote-repository.git
Do some changes and push them from your first repository to the remote repository via the following commands.
# Make some change in the first repos cd ~/repo01 # Make some changes in the file echo "Hello, hello. Turn your radio on" > test01 echo "Bye, bye. Turn your radio off" > test02 # commit the changes, -a will commit changes for modified files # but will not add automatically new files git commit -a -m "Some changes" # push the changes git push ../remote-repository.git
You can always push to a git repository via the full URL to it. But you can also add a "shortname" to a repository via the "git remote add" command. "origin" is a special name which is usually automatically used if you clone a git repository. Origin indicates the original repository from which you started. As we started from scratch this name is still available.
# Add ../remote-repository.git with the name origin git remote add origin ../remote-repository.git # Again some changes echo "I added a remote repo" > test02 # commit git commit -a -m "This is a test for the new remote origin" # If you don't label a repo it will push to origin git push origin
Checkout a new version of your repository into a new directory via the following commands.
# Switch to home cd ~ # make new directory mkdir repo02.git # Switch to new directory cd ~/repo02.git # git clone ../remote-repository.git .
Pull allows you to get the latest changes from another repository. In your new repository, make some changes, push them to your remote repository and pull these changes from your first repository.
# Switch to home cd ~ # Switch to second directory cd ~/repo02.git # Make changes echo "A change" > test01 # Commit git commit -a -m "A change" # Push changes to remote repository # origin is automatically maintained as we cloned from this repo git push origin # Switch to the first repository can pull in the changes cd ~/repo01.git git pull ../remote-repository.git/ # Check the changes less test01
If you create files in your working copy which you don't want to commit you can discard them.
# Create a new file with content touch test04 echo "this is trash" > test04 # Make a dry-run to see what would happen # -n is the same as --dry-run git clean -n # Now delete git clean -f
You can checkout older revisions of your source code via the commit name.
# Switch to home cd ~/repo01.git # get the log git log # Copy one of the older commits and checkout the older revision via git checkout commit_name
If you have not added the changes to the staging index you can also directly revert the changes.
#Some stupid change echo "stupid change" > test01 # Not added to the staging index therefore we can just checkout the old version git checkout test01 #check the result cat test01 # Another stupid change echo "another stupid change" > test01 # We add the file to the staging index git add test01 # restore the file in the staging index git reset HEAD test01 # get the old version from the staging index git checkout test01
You can also revert commits via.
#Revert a commit git revert commit_name
If you deleted a file but you have not yet added it to the index or commited the change you can checkout the file again.
You can also revert commits via.
// Delete a file rm test01 // Revert the deletion git checkout test01
If you added a file to the index but don't want to commit the file you can remove it from the index via git reset file
// create a file touch incorrect.txt // accicently add it to the index git add . // remove it from the index git reset incorrect.txt // delete the file rm incorrect.txt
Git has the option to tag certain versions in the history so that you later find then easier. Most commonly this is used to tag a certain version which has been released.
You can list the available tags via:
git tag
You can create a new tag via:
git tag -a version1.6 -m 'version 1.6'
If you want to use the code associated with the tag, use:
git checkout <tag_name>
Git allows to create branches, e.g. independent copies of the source code which can be changed independently from each other. The default branch is called "master". Git allows to create branches very fast and cheap in the sense of resource consumption. Developers are encouraged to use branches frequently.
The following command lists all available branches. The currently active branch is marked with "*".
git branch
You can create a new branch via the following.
# Syntax: git branch <name> <hash> # hash is optional if not specified the last commit will be used git branch testing # Switch to your new branch git checkout testing # Some changes echo "Cool new feature in this branch" > test01 git commit -a -m "new feature" #Switch the master branch git checkout master # Check that the content if test01 is the old one cat test01
Merge allows to combine the changes of two branches. Merge does perform a three way merge between the latest snapshot of two branches based on the most recent common ancestor of both. As a result you have a new snapshot. You can merge changes from one branch to the current active one via the following command.
# Syntax: git merge <branch-name. git merge testing
If a merge conflict occurs Git will mark the conflict in the file and the programmer has to manually fix the conflict. After resolving it he can add the file to the staging index and commit the change.
In addition to merge, Git allow also to use rebase. As described merge does combine the changes of two branches. Rebase takes the changes of a branch, creates a patch and apply it to another branch. The end result is the same as with merge but the commit history is cleaner; the history appears to be linear.
# Create new branch git branch testing # Checkout the branch git checkout experiment # Do some changes echo "This will be rebased to master" > test01 # Commit into testing branch git commit -a -m "New feature in branch" # Rebase the master git rebase master
Of course Git allows more then just committing and push and pulling. The following demonstrates how to work with branches and how to create patches.
The following helps you to see the changes in your repository.
// See the status git status // Shows a log file of the commits git log // This start a nice graphical view of the changes gitk --all
The following creates a branch, makes some changes in this branch, creates a patch and applies the patch to the master.
# Create a new branch git branch mybranch # Use this new branch git checkout mybranch # Do some changes touch test05 # Change some content in an existing file echo "New content for test01" >test01 # Commit these to the branch git add . git commit -a -m "First commit in the branch" # Create a patch --> git format-patch master git format-patch origin/master # Creates patch 0001-First-commit-in-the-branch.patch # Switch to the master git checkout master # Apply the patch git apply 0001-First-commit-in-the-branch.patch # Do your normal commit in the master git add . git commit -a -m "Applied patch" # delete the patch rm 0001-First-commit-in-the-branch.patch
Git allows of courses also remote operations. Git supports several transport types, the native one of Git is the "git protocol".
git clone git://dev.eclipse.org/org.eclipse.jface/org.eclipse.jface.snippets.git
Alternatively you could clone the same repository via a the http protocol.
git clone http://dev.eclipse.org/git/org.eclipse.jface/org.eclipse.jface.snippets.git
If you clone a remote repository the original repository will automatically stored as "origan" and if you have write access to the remote repository you can send your changes to it via "git push origin" You can add more remotes repositories to your repository via "git remote add name gitrepo". For example if you cloned the repository from above via the git protocol you could add the http protocol via:
// Add the http protocol git remote add githttp http://dev.eclipse.org/git/org.eclipse.jface/org.eclipse.jface.snippets.git
It is possible to use the HTTP protocol to clone Git repositories. That is especially helpful if your firewall blocks everything expect http. Git also support a proxy. For example the following command could clone a Eclipse project via http and a proxy. You can either set the proxy variable in general for all applications or set it only for git.
This example uses environment variables.
// Linux export http_proxy=http://proxy:8080 // On Windows // set http_proxy=http://proxy:8080 git clone http://dev.eclipse.org/git/org.eclipse.jface/org.eclipse.jface.snippets.git // push back to the origin using https git push origin
This example uses the git config settings.
// Set proxy for git globally git config --global http.proxy http://proxy:8080 // To check the proxy settings git config --get http.proxy // Just in case you need to you can also revoke the proxy settings git config --global --unset http.proxy
As described you don't need a server, you can just use a file system or a public git provider, as Github . But sometimes is it conviniant to have your own server and installing it under Ubuntu is very easy.
First make sure you have ssh installed.
apt-get install ssh
If you have not yet installed git then you need to do this also.
sudo apt-get install git-core
Create a new user for git.
sudo adduser git
Now logon to the git user and create a bare repository.
# login to server # to test use localhost ssh git@IP_ADDRESS_OF_SERVER # Create repository mkdir example.git cd example.git git --bare init
Now you can commit to the remote repository.
mkdir gitexample cd gitexample git init touch README git add README git commit -m 'first commit' git remote add origin git@IP_ADDRESS_OF_SERVER:example.git git push origin master
So far all operations we done have been done without a server. To use a server you can use the free hosting offering from Github .
Github requires you to create a ssh key. For creating such a key in Ubuntu please see ssh key creation in Ubuntu . For windows please see msysgit ssh key generation
Create an account at Github and create a repository. After creating a repository at GitHub you get a description which commands to run to upload for project. Follow these instructions.
Git provides the "git-svn" command line tool to run git against a svn repository. A good explanation for this can be found Git and svn .
git ships with two graphical tools. "gitk" shows the history and "git gui" show an editor which allows to perform git operations.
Similar to TortoiseSVN you can use TortoiseGit to have a integration into the file explorer under Windows.
The Eclipse EGit project provides Git integration into Eclipse. See Git with Eclipse for details.
Thank you for practicing with this tutorial.
I maintain this tutorial in my private time. If you like the information please help me by using flattr or donating or by
|
Before posting questions, please see the vogella FAQ . If you have questions or find an error in this article please use the www.vogella.de Google Group . I have created a short list how to create good questions which might also help you. .
Video with Linus Torwalds on Git
http://code.google.com/p/msysgit/ Git on Windows
http://github.com/guides/git-cheat-sheet Git Cheat Sheets
http://github.com/blog/626-announcing-svn-support SVN Support for GitHub
Git in 5 Minutes by Scott Paul Robertson
http://www.ibm.com/developerworks/opensource/library/l-git-subversion-1/index.html Git Intro for subversion users by Teodor Zlatanov