Git Tutorial
This tutorial explains the usage of the distributed
version
control system Git via the command line.
The examples were done on
Linux (Ubuntu) but should also work on other operating systems like
Microsoft Windows.
Table of Contents
- 1. Git
- 2. Tools
- 3. Terminology
- 4. Installation
- 5. Git Setup
- 6. Ignore certain files
- 7. Tracking empty directories with .gitkeep
- 8. Getting started with Git
- 9. Analyzing changes and the repository history
- 10. Changing the last commit and deleting files
- 11. Adding more repositories
- 12. Cloning remote repositories and push and pull
- 13. Revert Changes
- 14. Recovering lost commits
- 15. Tagging in Git
- 16. Branches
- 17. Merging branches
- 18. Solving merge conflicts
- 19. Rebase
- 20. Stash to save uncommited changes
- 21. Retrieving individual files
- 22. Create and apply patches
- 23. Define alias
- 24. Submodules - Repos inside other Git repos
- 25. Git workflows
- 26. Installing a Git server
- 27. Online remote repositories
- 28. Git Hosting Provider
- 29. Graphical UI's for Git
- 30. Get the Kindle edition
- 31. Questions and Discussion
- 32. Links and Literature
Git
is a distributed
version control system
(dvcs) written in the programming language
C.
A version control system allows the creation of a history for a collection of files and includes the functionality to revert the collection of files to another state. Another state might be a different collection of files or different content in the files. The collection of files is usually called source code.
A distributed version control system has no central server which stores the data. Every local copy contains the full history of the source code.
You may, for example, change the collection of files to a state from 2 days ago or you may switch between states for experimental features and production issues.
Git keeps track of all versions. Therefore you can revert to any point in your source code history.
A version control system allows the creation of a history for a collection of files and includes the functionality to revert the collection of files to another state. Another state might be a different collection of files or different content in the files. The collection of files is usually called source code.
A distributed version control system has no central server which stores the data. Every local copy contains the full history of the source code.
You may, for example, change the collection of files to a state from 2 days ago or you may switch between states for experimental features and production issues.
Git keeps track of all versions. Therefore you can revert to any point in your source code history.
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 use of a
dvcs
does not require a
central
code
repository.
Git commits file changes to your local repository and you can synchronize your repository with other (remote) repositories. Git allows you to clone repositories, e.g. create an exact copy of a repository including the complete history of the source code. Owners of repositories can synchronize changes via push (transferring changes to a remote repository) or pull (getting changes from a remote repository).
Git commits file changes to your local repository and you can synchronize your repository with other (remote) repositories. Git allows you to clone repositories, e.g. create an exact copy of a repository including the complete history of the source code. Owners of repositories can synchronize changes via push (transferring changes to a remote repository) or pull (getting changes from a remote repository).
Git
supports branching, e.g. you can have different versions of
your
source code. 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.
Branches in Git can be local. A branch created in a repository which was cloned from another repository does not need to have a counterpart in the remote repository.
Git allows to merge changes from different branches. For example you may have a branch called master which contains the source code which you use to build your product which is delivered to your customers. You use another branch called feature_123 to finalize a certain feature and then use the Git merge command to bring the changes into your master branch.
Branches in Git can be local. A branch created in a repository which was cloned from another repository does not need to have a counterpart in the remote repository.
Git allows to merge changes from different branches. For example you may have a branch called master which contains the source code which you use to build your product which is delivered to your customers. You use another branch called feature_123 to finalize a certain feature and then use the Git merge command to bring the changes into your master branch.
If you modify a file and you want to persist this change in the
repository you need to perform two steps in Git.
First you need to mark them to be relevant for Git. Marking changes as relevant for the version control is called staging or to add them to the index.
After adding the files to the index, you store this change n the Git repository. Storing the changes in the Git repository is called committing. A commit creates a new version of the whole repository.
For example, if you make a change in a file and want that this change is relevant for the next commit, you have to add the file to the index via the
First you need to mark them to be relevant for Git. Marking changes as relevant for the version control is called staging or to add them to the index.
After adding the files to the index, you store this change n the Git repository. Storing the changes in the Git repository is called committing. A commit creates a new version of the whole repository.
For example, if you make a change in a file and want that this change is relevant for the next commit, you have to add the file to the index via the
git add file
command. The
git commit -m "your commit message"
commits the marked changes into the
Git
repository.
There is huge varity of Git tools.
Git
can
be used from the command
line.
You also can use
graphical tools, for
example
EGit
for the Eclipse IDE.
The following table provides a summary of important
Git
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 a complete repository. The repository allows you to retrieve revisions into your working directory. |
Working directory | The working directory contains the content of a commit which you can checkout from the Git repository. You can modify the content and commit the changes again to the Git repository. |
Branches | A branch is a separate code line with its own history. You can create a new branch from an existing one and change the code independently from other branches. One of the branches is the default (normally named master). Selecting a branch in Git terminology is called to checkout a branch. |
Tags | A tag points to a commit which uniquely identifies a version of the Git repository. With a tag, you can have a named point to which you can always revert, e.g. the coding of 25.01.2009 in the branch "testing". |
Commit | You commit your changes into a repository. This creates a new commit object in the Git repository which uniquely identifies a new revision of the content of the repository. This revision which can be retrieved later, for example if you want to see the source code of an older version. Each commit object contains the author and the committer, thus making it possible to identify the source of the change. The author and committer might be different people. |
URL | A URL in Git determines the location of the repository. |
Revision | Represents a version of the source code. Git identifies revisions with SHA1 ids using a commit object. SHA1 ids are 160 bits long and are represented in hexadecimal. |
HEAD | HEAD is a pointer to the currently selected commit object. The version before that can be addressed via HEAD~1 and so on. |
On Ubuntu you can install the Git command line tool via the
following command:
To install Git on other Linux distributions please check your vendor documentation.
sudo apt-get install git-core
To install Git on other Linux distributions please check your vendor documentation.
A windows version of Git can be found on the
msysgit Project
site.
The URL to this webpage is listed below.
http://code.google.com/p/msysgit/
The easiest way to install Git on a Mac is via a graphical
installer. This installer can be found under the following URL.
As this procedure it not an official Apple one, it may change from time to time. The easiest way to find the current procedure is to Google for the "How to install Git on a Mac" search term.
http://code.google.com/p/git-osx-installer
As this procedure it not an official Apple one, it may change from time to time. The easiest way to find the current procedure is to Google for the "How to install Git on a Mac" search term.
Git allows you to store global settings in the
The following will configure Git so that a certain user and email address is used, enable color coding and tell Git to ignore certain files.
.gitconfig
file. This
file is located in the user home directory. Git stores
the
committer and author of a change in each commit. This and
additional
information
can be stored in the global settings.
The following will configure Git so that a certain user and email address is used, enable color coding and tell Git to ignore certain files.
Configure your user and email for Git via the following
command.
To make pushing to remote repositories easier and to avoid unnecessary commits, you can use the following commands.
# Configure the user which will be used by git # Of course you should use your name git config --global user.name "Example Surname" # Same for the email address git config --global user.email "your.email@gmail.com"
To make pushing to remote repositories easier and to avoid unnecessary commits, you can use the following commands.
# Set default so that all changes are always pushed to the repository git config --global push.default "matching" # Set default so that you avoid unnecessary commits git config --global branch.autosetuprebase always
The following will enable some highlighting for the console.
git config --global color.status auto git config --global color.branch auto
Git can be configured to ignore certain files and directories. This
is
configured via the
You can use certain wildcards in this file.
You can also setup a global
The local
.gitignore
file.
This file can be in any directory and can contain patterns for
files.
For example, you can tell Git to ignore the
bin
directory
via the
following
.gitignore
file
in the main directory.
You can use certain wildcards in this file.
*
will match several characters.
The
.
(Dot) parameter
will match one character.
# Ignore all bin directories
bin
# Ignore all files ending with ~
*~
# Ignore the target directory
# Matches "target" in any subfolder
target/
You can also setup a global
.gitignore
file valid for all Git repositories via the
core.excludesfile
setting.
# Create a ~/.gitignore in your user directory cd ~/ touch .gitignore # Exclude bin and .metadata directories echo "bin" >> .gitignore echo ".metadata" >> .gitignore echo "*~" >> .gitignore echo "target/" >> .gitignore # Configure Git to use this file # as global .gitignore git config --global core.excludesfile ~/.gitignore
The local
.gitignore
file can be committed into the Git repository and
therefore is visible
to everyone who clones the repository. The
global
.gitignore
file is only
locally visible.
Git ignores empty directories, i.e. it does not put them under
version control. If you want to track such a directory, it is
a common practice
to put a file
called
.gitkeep
in
the directory. The
file
could be called
anything; Git assigns no
special significance to
this
name. As the directory now contains a
file, Git will include it into
its version control mechanism.
In this chapter you create
a few files, create a local Git repository and commit
your
files into this repository. The comments
(marked with #) before
the
commands
explain
the specific actions.
Open a command line / shell for the operations.
Open a command line / shell for the operations.
The following commands create an empty directory which will be
used as Git repository.
#Switch to home
cd ~/
# Create a directory
mkdir ~/repo01
# Switch into it
cd repo01
# Create a new directory
mkdir datafiles
Every Git repository is stored in the
The following will create a Git repository in the current directory.
.git
folder of the
directory in which the Git repository has been created.
This
directory
contains the complete history of the
repository.
The
.git/config
file
contains the local
configuration for the
repository.
The following will create a Git repository in the current directory.
# Initialize the Git repository
# for the current directory
git init
The following commands create some files with some content that
will
be placed under version control.
# Switch to your new directory cd ~/repo01 # 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
Before committing to a Git repository you need to mark which
changes should be committed by adding the new and changed files to
the Git index. i.e. the staging area. This creates a snapshop of the
affected
files, if you afterwards change one of the files before
committing, you
need to add it again to the index to commit the new
changes.
# Add all (files and directories) to the index of the # Git repository git add .
After adding the files to the Git index, you can commit them to
the Git repository. This creates a new snapshot of all your files in your Git
repository.
# Make a commit of your file to the local repository
git commit -m "Initial commit"
# Show the log file with the commits
git log
The
git diff
command allows the user to see the changes made. In order to test
this, make some changes to a file and check what the
git diff
command shows to you.
Then,
commit the changes to the repository.
# Make some changes to 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"
The following commands show the current status
of your
repository, i.e. which files have changed and the changes in
the files
between the last commit.
# Make some changes in the file echo "This is a new change" > test01 echo "and this is another new change" > test02 # See the current status of your repository # (which files are changed / new / deleted) git status # Show the differences between the uncommitted files # and the last commit in the current branch git diff # Add the changes to the index and commit git add . && git commit -m "More chaanges - typo in the commit message"
The
git log
commands shows the history of your repository in the current branch,
i.e. the list
of
commits.
# Show the history of commits in the current branch git log # Show the history of commits in one line # with a shortened version of the commit id git log --oneline --abbrev-commit # Show the history as graph including branches git log --graph --pretty --oneline --abbrev-commit
To see the files which have been changed in a commit use the
following command.
To see the changes in a commit use the following command.
git diff-tree --name-only -r <commit_id>
To see the changes in a commit use the following command.
git show <commit_id>
To see changes in a file you can use the
-p
option in the
git log
command.
# git log filename shows the commits for this file git log [filename] # Use -p to see the diffs of each commit git log -p filename # --follow shows the entire history # including renames git log --follow -p file
The
git blame
command allows you to see which commit and author
modified a file on a
line by line basis.
# git blame shows the author and commit per # line of a file git blame [filename] # the -L option allows to limit the selection # for example by line number # only show line 1 and 2 in git blame git blame -L 1-2 [filename]
The git amend command makes it possible to change the last
commit message.
In the above example the commit message was incorrect as it contained a typo. The following will correct this via the
In the above example the commit message was incorrect as it contained a typo. The following will correct this via the
--amend
parameter.
git commit --amend -m "More changes - now correct"
If you delete a file which is under version control
You can use the
Alternatively you can use the git commit command with the
git add .
will not pick this file up.
You can use the
git -rm
command to delete the file from your working directory and mark it
for the next commit.
# Create a file and put it under version control touch nonsense2.txt git add . && git commit -m "more nonsense" # Remove the file via Git git -rm nonsense2.txt # Commit the removal git commit -m "Removes nonsense2.txt file"
Alternatively you can use the git commit command with the
-a
flag or the
-A
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 nonsense.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 nonsense.txt is now removed" # Alternatively you could add deleted files to the staging index via git add -A . git commit -m "File nonsense.txt is now removed"
We will now create a remote Git repository. Git
allows you to
store
this remote repository either on the network or locally.
A standard Git repository is different from a remote Git repository. A standard Git repository contains the working directory (single checkout of one version of the project) and the Git repository. You can work in this working directory by modifying content and committing the changes to the Git repository.
Remote repositories do not contain working copies of the files. They only contain repository files. To create such a repository, set the
In order to simplify the following examples, the Git repository will be created locally in the filesystem.
A standard Git repository is different from a remote Git repository. A standard Git repository contains the working directory (single checkout of one version of the project) and the Git repository. You can work in this working directory by modifying content and committing the changes to the Git repository.
Remote repositories do not contain working copies of the files. They only contain repository files. To create such a repository, set the
--bare
flag.
In order to simplify the following examples, the Git repository will be created locally in the filesystem.
# Switch to the first repository cd ~/repo01 # git clone --bare . ../remote-repository.git # Check the content, it is identical to the .git directory in repo01 ls ~/remote-repository.git
You can always push to a Git repository via its full URL.
But you can
also add a
shortname
to a repository via the
git
remote add
command.
origin
is a special name which is normally used
automatically, 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 do not label a repository it will push to origin git push origin
Clone a repository and checkout a working copy in a new
directory
via the following
commands.
# Switch to home cd ~ # Make new directory mkdir repo02 # Switch to new directory cd ~/repo02 # Clone git clone ../remote-repository.git .
Make some changes and push them from your first repository to
the
remote repository
via the following commands.
# Make some changes in the first repository 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
Pull allows you to get the latest changes from another
repository. In your second repository, make some changes, push them
to
your
remote repository and pull these changes to your first
repository.
# Switch to home cd ~ # Switch to second directory cd ~/repo02 # 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 repository git push origin # Switch to the first repository and pull in the changes cd ~/repo01 git pull ../remote-repository.git/ # Check the changes less test01
If you create files in your working copy which you do not want
to
commit, you can discard them with the
If you deleted or changes a file but you have not yet added it to the index or committed the change, you can check out the file again.
git clean
command.
# Create a new file with content echo "this is trash to be deleted" > 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
If you deleted or changes a file but you have not yet added it to the index or committed the change, you can check out the file again.
# Delete a file
rm test01
# Revert the deletion
git checkout test01
# Change a file
echo "override" > test01
# Restore the file
git checkout test01
You can check out older revisions of your source code via the
commit
ID. The commit ID is shown if you enter the
If you have added the changes to the staging index, you can also revert the changes in the index and checkout the file from the index.
If you add a file to the index but do not want to commit the file, you can remove it from the index via the
If you deleted a directory and you have not yet committed the changes, you can restore the directory via the following command:
git log
command.
It is displayed behind the
commit
word.
# Switch to home cd ~/repo01 # Get the log git log # Checkout the older revision via git checkout commit_id
If you have added the changes to the staging index, you can also revert the changes in the index and checkout the file from the index.
#Some nonsense change echo "nonsense 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 nonsense change echo "another nonsense 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
If you add a file to the index but do not want to commit the file, you can remove it from the index via the
git reset file
command.
# Create a file touch incorrect.txt # Accidently add it to the index git add . # Remove it from the index git reset incorrect.txt # Delete the file rm incorrect.txt
If you deleted a directory and you have not yet committed the changes, you can restore the directory via the following command:
git checkout HEAD -- your_dir_to_restore
You can revert commits via the
You can also delete a commit with the
git revert
command.
git revert
will revert the changes of a commit and record a new commit which
documents that the other commit was reverted.
# Revert a commit git revert commit_id
You can also delete a commit with the
git reset --hard
command. To push such a change you need to use the
--force
parameter. In case you pushed a commit already, you should better use
the
git revert
command.
# Delete the commit before head # ~2 would delete the last two, etc git reset --hard HEAD~1 # Delete up to a certain commit git reset --hard <sha1-commit-id>
If you want to undo all changes in your working directory
including the deletion of new file you can use the following
commands. Please note that you may lose data by these commands.
# Removes staged and working directory changes
git reset --hard
# Removes new files which are still untracked
git clean -f -d
Sometimes you change your
If you want to remove the related files from your Git repository you need to do this explicitely via the following command. use.
This will not remove the file from the commit history. If the file should also be removed from the history, have a look at
.gitignore
file. Git will
stop
tracking the new entries from this moment. The last
version
is still in the Git repository.
If you want to remove the related files from your Git repository you need to do this explicitely via the following command. use.
# Remove directory .metadata from git repo git rm -r --cached .metadata # Remove file test.txt from repo git rm --cached test.txt
This will not remove the file from the commit history. If the file should also be removed from the history, have a look at
git
filter-branch
which allows you to rewrite the commit history.
The Git reflog command gives a history of the complete
changes
of your
current branch based on the
HEAD
revision.
Git reflog lists also commits which you removed.
git reflog # Output # ... snip ... 1f1a73a HEAD@{2}: commit: More chaanges - typo in the commit message 45ca204 HEAD@{3}: commit: These are new changes cf616d4 HEAD@{4}: commit (initial): Initial commit
Git reflog lists also commits which you removed.
The following example shows how you can use git reflog to revert
to a commit which has been removed.
# Assume the ID for the second commit is # 45ca2045be3aeda054c5418ec3c4ce63b5f269f7 # Resets the head for your tree to the second commit git reset --hard 45ca2045be3aeda054c5418ec3c4ce63b5f269f7 # See the log git log # Output shows the history until the 45ca2045be commit # See all the history including the deletion git reflog # <Output> cf616d4 HEAD@{1}: reset: moving to 45ca2045be3aeda054c5418ec3c4ce63b5f269f7 # ...snip.... 1f1a73a HEAD@{2}: commit: More chaanges - typo in the commit message 45ca204 HEAD@{3}: commit: These are new changes cf616d4 HEAD@{4}: commit (initial): Initial commit git reset --hard 1f1a73a
Git has the option to tag certain versions in the history so
that
you find them more easily at a later point in time. Most
commonly,
this is used to tag a
certain version which has been
released.
You can list the available tags via the following command:
You can list the available tags via the following command:
git tag
You can create a new tag via the
You can also create tags for a certain commit id.
If you want to use the code associated with the tag, use:
git tag
command. Via the
-m
parameter, you specify the description of this tag. The following
command tags the current active HEAD.
git tag version1.6 -m 'version 1.6'
You can also create tags for a certain commit id.
git tag version1.5 -m 'version 1.5' [commit id]
If you want to use the code associated with the tag, use:
git checkout <tag_name>
Git allows you to create
branches, i.e. independent copies of the source code which can be changed
independently from each other. The default branch is called
master.
Git allows you to create branches very fast and cheaply in terms of resource consumption. Developers are encouraged to use branches frequently.
If you decide to work on a branch, you checkout this branch. This means that Git moves the HEAD pointer to the latest commit of the branch and populates the Working directory with the content of this commit.
Untracked files remain unchanged and are available in the new branch. This allows you to create a branch for unstaged and uncommited changes at any point in time.
Git allows you to create branches very fast and cheaply in terms of resource consumption. Developers are encouraged to use branches frequently.
If you decide to work on a branch, you checkout this branch. This means that Git moves the HEAD pointer to the latest commit of the branch and populates the Working directory with the content of this commit.
Untracked files remain unchanged and are available in the new branch. This allows you to create a branch for unstaged and uncommited changes at any point in time.
The
If you want to see all branches (including remote tracking branches), use the
git branch
command lists all
locally available branches. The
currently
active
branch is marked with
*
.
# lists available branches git branch
If you want to see all branches (including remote tracking branches), use the
-a
for the
git branch
command.
# lists all branches including the remote branches git branch -a
You can create a new branch via the
To create a branch and to switch to it at the same time you can use the
git branch [newname]
command. This command allows optional to specify the commit id, if
not specified the currently
checked out commit will be used to create
the branch.
# Syntax: git branch <name> <hash> # <hash> in the above is optional 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 to the master branch git checkout master # Check that the content of test01 is the old one cat test01
To create a branch and to switch to it at the same time you can use the
git checkout
command with the
-b
parameter.
# Create branch and switch to it git checkout -b bugreport12 # Creates a new branch based on the master branch # without the last commit git checkout -b mybranch master~1
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
By default Git will only push matching branches to a remote
repository. That means that you have to manually push a new branch
once. Afterwards "git
push" will also push the new branch.
This way you can decide which branches should be visible to other repositories and which should be local branches.
# Push testing branch to remote repository git push origin testing # Switch to the testing branch git checkout testing # Some changes echo "News for you" > test01 git commit -a -m "new feature in branch" # Push all including branch git push
This way you can decide which branches should be visible to other repositories and which should be local branches.
Git allows to combine the changes of two
branches. This process is called
merging.
Merge performs a so-called 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 in the branch onto which you merged the changes of the other branch.
Merge performs a so-called 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 in the branch onto which you merged the changes of the other branch.
A merge conflicts occurs, if two people have modified the same
content and Git cannot automatically determine how both changes
should
be applied.
If a merge conflict occurs Git will mark the conflict in the file and the programmer has to resolve the conflict manually. After resolving it, he can add the file to the staging index and commit the change.
If a merge conflict occurs Git will mark the conflict in the file and the programmer has to resolve the conflict manually. After resolving it, he can add the file to the staging index and commit the change.
The following example
first creates a merge
conflict and then
resolve it and
apply the change to
the Git
repository.
The following code will create a merge conflict.
Git marks the conflict in the affected file. This file looks like the following.
The above is the part from your repository and the below one from the remote repository. You could now edit the file manually and then commit the changes. Alternatively, you could use the
The following code will create a merge conflict.
# Switch to the first directory cd ~/repo01 # Make changes echo "Change in the first repository" > mergeconflict.txt # Stage and commit git add . && git commit -a -m "Will create merge conflict 1" # Switch to the second directory cd ~/repo02 # Make changes touch mergeconflict.txt echo "Change in the second repository" > mergeconflict.txt # Stage and commit git add . && git commit -a -m "Will create merge conflict 2" # Push to the master repository git push # Now try to push from the first directory # Switch to the first directory cd ~/repo01 # Try to push --> you will get an error message git push # Get the changes git pull origin master
Git marks the conflict in the affected file. This file looks like the following.
<<<<<<< HEAD Change in the first repository ======= Change in the second repository >>>>>>> b29196692f5ebfd10d8a9ca1911c8b08127c85f8
The above is the part from your repository and the below one from the remote repository. You could now edit the file manually and then commit the changes. Alternatively, you could use the
git mergetool
command.
git mergetool
starts a
configurable merge tool that displays the changes in a
split
screen.
# Either edit the file manually or use git mergetool # You will be prompted to select which merge tool you want to use # For example on Ubuntu you can use the tool "meld" # After merging the changes manually, commit them git commit -m "merged changes"
The
The following will create several commits which should be combined at a later point in time.
We will combine the last seven commits. You can do this interactively via the following command.
This will open your editor of choice and let you edit the commit message or
Squash will combine the commit messages while
rebase
command allows you to combine several commits into
one commit. This is
useful as it allows the user to rewrite some of the
commit history
(cleaning it up) before pushing your changes to a
remote repository.
The following will create several commits which should be combined at a later point in time.
# Create a new file touch rebase.txt # Add it to git git add . && git commit -m "rebase.txt added to index" # Do some silly changes and commit echo "content" >> rebase.txt git add . && git commit -m "added content" echo " more content" >> rebase.txt git add . && git commit -m "added more content" echo " more content" >> rebase.txt git add . && git commit -m "added more content" echo " more content" >> rebase.txt git add . && git commit -m "added more content" echo " more content" >> rebase.txt git add . && git commit -m "added more content" echo " more content" >> rebase.txt git add . && git commit -m "added more content" # Check the git log message git log
We will combine the last seven commits. You can do this interactively via the following command.
git rebase -i HEAD~7
This will open your editor of choice and let you edit the commit message or
squash
/
fixup
the commit with the last one.
Squash will combine the commit messages while
fixup
will disregard
the commit
message.
You can use Git to rebase one branches on another one. As described
the
The final result for the source code is the same as with merge but the commit history is cleaner; the history appears to be linear.
merge
command
combines the changes of two branches. Rebase takes
the
changes
of
a
branch,
creates a patch for each commit and applies it to the other
branch.
The final result for the source code 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 testing # Make some changes echo "This will be rebased to master" > test01 # Commit into testing branch git add test01 git commit -m "New feature in branch" # Rebase the master git checkout master git rebase testing
You should always check your local branch history before pushing
changes to another Git repository or review system.
Git allows you to do local commits. This feature is frequently used to have points to which you can go back, if something should go wrong later during a feature development. If you do so you, before pushing, should look at your local branch history and validate, whether or not these commits are relevant for others.
If they all belong to the implementation of the same feature you, most likely, want to summarize them in one single commit before pushing.
The interactive rebase is basically rewriting the history. It is safe to do this as long as the commits have not been pushed to another repository. This means commits should only be rewritten as long as they have not been pushed.
If you rewrite and push a commit that is already present in other Git repositories, it will look as if you implemented something that somebody already implemented in the past.
Git allows you to do local commits. This feature is frequently used to have points to which you can go back, if something should go wrong later during a feature development. If you do so you, before pushing, should look at your local branch history and validate, whether or not these commits are relevant for others.
If they all belong to the implementation of the same feature you, most likely, want to summarize them in one single commit before pushing.
The interactive rebase is basically rewriting the history. It is safe to do this as long as the commits have not been pushed to another repository. This means commits should only be rewritten as long as they have not been pushed.
If you rewrite and push a commit that is already present in other Git repositories, it will look as if you implemented something that somebody already implemented in the past.
Git provides the
This allows you to pull in the latest changes or to develop an urgent fix. Afterwards you can restore the stashed changes, which will reapply the changes to the current version of the source code.
In general using the stash command should be the exception in using Git. Typically you would create new branches for new features and switch between branches.
stash
command which allows to save the current uncommmitted changes and
checkout
the last committed revision.
This allows you to pull in the latest changes or to develop an urgent fix. Afterwards you can restore the stashed changes, which will reapply the changes to the current version of the source code.
In general using the stash command should be the exception in using Git. Typically you would create new branches for new features and switch between branches.
The following commands will save a stash and reapply them
after
some changes.
It is also possible to keep a list of stashes.
# Create a stash with uncommited changes git stash # TODO do changes to the source, e.g. by pulling # new changes from a remove repo # Afterwards reapply the stashed changes # and delete the stash from the list of stashes git stash pop
It is also possible to keep a list of stashes.
# Create a stash with uncommited changes git stash save # See the list of available stashes git stash list # Result might be something like: stash@{0}: WIP on master: 273e4a0 Resize issue in Dialog stash@{1}: WIP on master: 273e4a0 Silly typo in Classname # You can use the ID to apply a stash git stash apply stash@{0} # Also you can remove a stashed change git stash drop stash@{0} # Or delete all stashes git stash clear # Or apply the latest stash and delete it afterwards git stash pop # Afterwards reapply the stashed changes # and delete the stash from the list of stashes git stash pop
The
The following commands demonstrate that. You can also make a copy of the file.
git show
command allows to see and retrieve files from branches and commits.
It allows to see files from branches or commits without switches to
these branches or commits.
The following commands demonstrate that. You can also make a copy of the file.
# [reference] can be a branch, tag, HEAD or commit ID # [filename] is the filename including path git show [reference]:[filename] # To make a copy to copiedfile.txt git show [reference]:[filename] > copiedfile.txt
A
patch
is a text file that contains changes to the source code. This file
can
be sent to someone else and this person can use this file to apply
the
changes to his/her local repository.
The following example
creates a branch, changes the files and
commits these changes into the branch.
The next example creates a patch for these changes.
To apply this patch to your master branch, switch to it and use the
Afterwards you can commit the changes introduced by the patches and delete the patch file.
# Create a new branch git branch mybranch # Use this new branch git checkout mybranch # Make some changes touch test05 # Change some content in an existing file echo "New content for test01" >test01 # Commit this to the branch git add . git commit -a -m "First commit in the branch"
The next example creates a patch for these changes.
# Create a patch --> git format-patch master
git format-patch origin/master
# This created the file:
# patch 0001-First-commit-in-the-branch.patch
To apply this patch to your master branch, switch to it and use the
git apply
command.
# Switch to the master
git checkout master
# Apply the patch
git apply 0001-First-commit-in-the-branch.patch
Afterwards you can commit the changes introduced by the patches and delete the patch file.
# Patch is applied to master # Change can be commited git add . git commit -a -m "Applied patch" # Delete the patch file rm 0001-First-commit-in-the-branch.patch
An alias in Git allows you to setup your own Git command. For
example, you can define an alias which is a short form of your own
favorite commands or you can
combine
several commands with an alias.
Unfortunately, defining an alias is at the time of writing not completely supported in msysGit for Windows. You can do single aliases, e.g.
Unfortunately, defining an alias is at the time of writing not completely supported in msysGit for Windows. You can do single aliases, e.g.
ca
for
ca
= commit -a) but you
can not do ones beginning with
!
.
Git allows you to include another Git repository into a Git
repository. This is useful in case you want to include a certain
library in another repository of in case you want to aggregate
certain Git repositories. Git call these included Git repository
submodules.
Git allows you to commit, pull and push to these repositories independently.
You add a submodule to a Git repository via the
Git allows you to commit, pull and push to these repositories independently.
You add a submodule to a Git repository via the
git submodule add
command.
# Add a submodule to your Git repo git submodule add [URL to Git repo]
To clone a Git repository which contains submodules you need to run
in addition to the clone command the
git submodule init
and
git submodule update
command. The init command creates the local configuration file for
the submodules if it does not yet exists and the update command
clones the submodules.
The following description highlights typical Git workflows.
Git emphasizes the creation of branches for feature development
or
to create
bug fixes. The following description lists a typical Git
workflow for
fixing a bug in your source code (files) and providing a
patch for it. This patch contains the changes and can be used by
another person to apply the changes to his local Git repository.
This description assumes that the person which creates the changes cannot push changes directly to the remote repository. For example you may solve an issue in the source code of an Open Source project and want that the maintainer of the Open Source project integrates this into his project.
You may also want to commit several times during 3.) and 4.) and rebase your commits afterwards.
Even if you have commit rights, creating a local branch for every feature or bug fix is a good practice. Once your development is finished you merge your changes to your master and push the changes from master to your remote Git repository.
This description assumes that the person which creates the changes cannot push changes directly to the remote repository. For example you may solve an issue in the source code of an Open Source project and want that the maintainer of the Open Source project integrates this into his project.
-
Clone the repository, in case you have not done that.
-
Create a new branch for the bug fix
-
Modify the files (source code)
-
Commit changes to your branch
-
Create patch
-
Send patch to another person or attach it to a bug report, so
that is can be applied to the other Git repository
You may also want to commit several times during 3.) and 4.) and rebase your commits afterwards.
Even if you have commit rights, creating a local branch for every feature or bug fix is a good practice. Once your development is finished you merge your changes to your master and push the changes from master to your remote Git repository.
Sometimes you want to add another remote repository to your
local Git repo and pull and push from and two both repositories.
The
following example describes how to add another remote
repository
and to
pull
and fetch from both repositories.
You can add another remote repository called remote_name via the following command.
For merging the changes in remote_name create a new branch called newbranch.
Afterwards you can pull from your new repository called remote_name and push to your original repository.
You can add another remote repository called remote_name via the following command.
# add remote git remote add <remote_name> <url_of_gitrepo> # see all repos git remote -v
For merging the changes in remote_name create a new branch called newbranch.
# create a new branch which will be used # to merge changes in repository 1 git checkout -b <newbranch>
Afterwards you can pull from your new repository called remote_name and push to your original repository.
# reminder: your active branch is newbranch # pull remote_name and merge git pull <remote_name> # or fetch and merge in two steps git fetch <remote_name> git merge <remote_name>/<newbranch> # afterwards push to first repository git push -u origin master
As described before, you do not need a server. You can just use a file
system or
a public Git provider, such as
Github or Bitbucket. Sometimes, however, it is convenient to have your own server, and
installing it under Ubuntu is relatively easy.
First make sure you have installed ssh.
If you have not yet installed Git on your server, you need to do this too.
Create a new user for git.
Now log on with your Git user and create a bare repository.
Now you can commit to the remote repository.
First make sure you have installed ssh.
apt-get install ssh
If you have not yet installed Git on your server, you need to do this too.
sudo apt-get install git-core
Create a new user for git.
sudo adduser git
Now log on with your Git user and create a bare repository.
# Login to server
# to test use localhost
ssh git@IP_ADDRESS_OF_SERVER
# Create repository
git init --bare example.git
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
Git also support remote
operations. Git supports
several transport
types; the native protocol for Git is also called
The following will clone an existing repository via the Git protocol.
Alternatively you could clone the same repository via the
git
.
The following will clone an existing repository via the Git protocol.
git clone git@github.com:vogella/gitbook.git
Alternatively you could clone the same repository via the
http
protocol.
# The following will clone via HTTP git clone http://vogella@github.com/vogella/gitbook.git
If you clone a remote repository, the original repository will
automatically be called
You can push changes to this origin repository via
You can add more remote repositories to your repository via the
origin
.
You can push changes to this origin repository via
git push
origin
. Of course, pushing to a remote repository requires write access to
this
repository.
You can add more remote repositories to your repository via the
git
remote
add name gitrepo
command. For example if you cloned the
repository from
above
via the Git
protocol, you could add the http
protocol via:
// Add the https protocol git remote add githttp https://vogella@github.com/vogella/gitbook.git
It is possible to use the HTTP protocol to clone Git
repositories. This
is especially helpful, if your firewall blocks
everything except http.
Git also provides support for http access via a proxy server. The following Git command could, for example, clone a repository 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.
This example uses the Git config settings.
Git also provides support for http access via a proxy server. The following Git command could, for example, clone a repository 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 http 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
Instead of setting up your own server, you can also use a
hosting
service. The most popular Git hosting sites are GitHub and Bitbucket.
Both offer free hosting with certain limitations.
Most hosting provider allow to use the
http
protocol with manual user authentication or to use an ssh key for
automatic authentication.
An ssh key has a public and private part. The public part is uploaded to the hosting provider. If you interact with the hosting provider via ssh, the public key will be validated based on the private key which is hold locally.
The ssh key is usually generated in the
To create an ssh key under Ubuntu switch to the command line and issue the following commands.
The result will be two files,
You find more details for the generation of a rsa key on the following webpages.
An ssh key has a public and private part. The public part is uploaded to the hosting provider. If you interact with the hosting provider via ssh, the public key will be validated based on the private key which is hold locally.
The ssh key is usually generated in the
.ssh
directory. Ensure that you backup existing keys in this directory
before running the following commands.
To create an ssh key under Ubuntu switch to the command line and issue the following commands.
# Switch to your .ssh directory cd ~/.ssh # If the directory # does not exist, create it via: # mkdir .ssh # Manually backup all existing content of this dir!!! # Afterwards generate the ssh key ssh-keygen -t rsa -C "your_email@youremail.com" # Press enter to select the default directory # You will be prompted for an optional passphrase # A passphrase protects your private key # but you have to enter it manually during ssh operations
The result will be two files,
id_rsa
which is your private key and
id_rsa.pub
which is your public key.
You find more details for the generation of a rsa key on the following webpages.
# Link to ssh key creation on Github https://help.github.com/articles/generating-ssh-keys
GitHub can be found
under the
URL https://github.com/. GitHub is
free for all public repositories, i.e. if you want to have private
repositories which are only visible
to people you select, you have to
pay GitHub a monthly fee.
Create an account at GitHub and create a repository. After creating a repository at GitHub you will get a description of all the commands you need to execute to upload your project to GitHub. Follow the instructions.
These instructions will be similar to the following:
Create an account at GitHub and create a repository. After creating a repository at GitHub you will get a description of all the commands you need to execute to upload your project to GitHub. Follow the instructions.
These instructions will be similar to the following:
Global setup: Set up git git config --global user.name "Your Name" git config --global user.email your.email@gmail.com Next steps: mkdir gitbook cd gitbook git init touch README git add README git commit -m 'first commit' git remote add origin git@github.com:vogella/gitbook.git git push -u origin master Existing Git Repo? cd existing_git_repo git remote add origin git@github.com:vogella/gitbook.git git push -u origin master
Bitbucket can be found
under the
URL https://bitbucket.org/.
Bitbucket allows unlimited public and private repositories, while the
number of participants for one private repository is currently
limited to 5 collaborators. I.e. if you have more then 5 developers
which need access to a private repository you have to pay money to
Bitbucket.
This tutorial focused on the usage of the command line for Git.
After
finishing this tutorial, you may want to look at graphical tools
for working with Git.
Git provides two graphical tools.
The Eclipse EGit project provides Git integration into Eclipse, which is included in the latest Eclipse release.
Git provides two graphical tools.
gitk
shows the history and
git gui
shows an editor that allows you to perform Git
operations.
The Eclipse EGit project provides Git integration into Eclipse, which is included in the latest Eclipse release.
Before posting questions, please see the
vogella FAQ. If you have questions or find an error in this article please
use the
www.vogella.com Google Group. I have created a short list
how to create good questions
which might also help you.
Git homepage
EGit - Teamprovider for Eclipse
Video with Linus Torvalds on Git
Git on Windows
from http://www.vogella.com/articles/Git/article.html
EGit - Teamprovider for Eclipse
Video with Linus Torvalds on Git
Git on Windows
from http://www.vogella.com/articles/Git/article.html