1. Git 1.1. What is Git? 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 . 1.2. Important terminology 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. 1.3. Staging index 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. 2. Installation 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 3. Setup 3.1. User Configuration 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 3.2. Ignore certain files 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 Git has also the global setting "core.excludesfile" for specifying global excludes. 4. Getting started with Git 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. 4.1. Create content 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 4.2. Create repository, add and commit 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. 4.3. Commit changes 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" 4.4. Correct commit message - git amend 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" 4.5. Delete files If you delete a file which is under version control "git add ." will not pick this file up. You need to use the git commit command with the -a flag or to use the -u flag in the git add command. # Create a file and put it under version control touch nonsense.txt git add . && git commit -m "a new file has been created" # Remove the file rm nosense.txt # Try standard way of committing -> will not work git add . && git commit -m "a new file has been created" # Now commit with the -a flag git commit -a -m"File nosense.txt is now removed" # Alternatively you could add deleted files to the staging index via git add -u . 4.6. Setting up a remote git repository 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 4.7. Push changes to another repository 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 4.8. Add remote 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 4.9. Clone your repository 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 . 4.10. Push and pull some changes 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 5. Revert Changes 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 6. Tagging in Git 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> 7. Branches and Merging 7.1. Branches 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 7.2. Merging 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. 7.3. Delete a branch To delete a branch which is not needed anymore you can use the following command. #Delete branch testing git branch -d testing # Check if branch has been deleted git branch 8. Solving merge conflicts Git allows to solve merge conflicts. The following will create a merge conflict. # Switch to first directory cd ~/repo01.git # Make changes touch mergeconflict.txt echo "Change in the first repo" > mergeconflict.txt # Stage and commit git add . && git commit -a -m "Will create merge conflict repo1" # Switch to second directory cd ~/repo02.git # Make changes touch mergeconflict.txt echo "Change in the second repo" > mergeconflict.txt # Stage and commit git add . && git commit -a -m "Will create merge conflict repo2" # Try to push to the master repo git push # Switch to first directory cd ~/repo01.git # Try to push --> you will get an error message git push # Get the changes git pull master origin Git marks the conflict in the affected file. This file looks like the following. <<<<<<< HEAD Change in the first repo ======= Change in the second repo >>>>>>> b29196692f5ebfd10d8a9ca1911c8b08127c85f8 The above part is the part from your repo and the below one from the remote repository. You could now edit the file manually and then commit the changes. Alternatively you could use "git mergetool" which would use a configurable merge tool which displays the changes in a split screen. # Either edit the file manually or use git mergetool # You will be prompted which merge tool you want to use # on Ubuntu I use meld # After manually merging the changes, commit them git commit -m "merged changes" 9. Rebase 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 10. Working with Git 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. 10.1. Status and change log 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 10.2. Create and apply patch 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 11. Remote repository 11.1. Cloning remote repositories 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 11.2. Add more remotes 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 11.3. Remote operations via http and a proxy 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 12. Installating a git server 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 13. GitHub 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. 14. Git and svn 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 . 15. Graphical UI's for Git 15.1. UI for Git git ships with two graphical tools. "gitk" shows the history and "git gui" show an editor which allows to perform git operations. 15.2. TortoiseGit for Microsoft Similar to TortoiseSVN you can use TortoiseGit to have a integration into the file explorer under Windows. 15.3. Eclipse and EGit The Eclipse EGit project provides Git integration into Eclipse. See Git with Eclipse for details. |