2. BASIC CONCEPTS
What is GIT?
● DVCS
GIT Architecture
● Working Copy
● Staging Index (a.k.a. index)
● Local Repository (a.k.a. repo or repository)
● Remote Repository (a.k.a. remote)
3. GIT Architecture
DEV MACHINE ORIGIN
REMOTE SERVER
DEV1
DEV MACHINE
DEV2 DEV3
REMOTE MERGE
LOCAL MACHINE
INDEX
WORKING REPO
COPY
5. GIT ARCHITECTURE
git commit
git add
INDEX: works as a staging area
between working copy and repo
REPO
GIT Objects
● blob: stores the data
WORKING COPY ● tree: reference other trees and
blobs (directories)
● commit: references to a tree
and contains all the info of a
commit
● tag: mark a reference to a
specific object
6. .git Directory File Structure
Contains all the information to recreate the tree
history
|-- HEAD (pointer to the current branch)
|-- config (holds the configuration preferences)
|-- description (description of your project)
|-- hooks/ (pre/post action hooks)
|-- index (contains the index of the repo)
|-- logs/ (a history of where the branches have been)
|-- objects/ (the objects (commits, trees, blobs, tags)
`-- refs/ (reference to important commit objects)
7. GIT most common commands
init: Initialize a repository, initialize it empty with the --bare
option or based on existing content
branch: Creates a new branch/Show all branches
clone: Initialize a repository and working directory from a
remote repository
checkout: This has several purposes: Change branch or
revert a file or directory
stash: Temporarily saves the changes and wipe those
changes from the index and working copy
8. GIT most common commands
status: Displays informational data about the
local repository, files added to the index and
current branch
add: Adds changes to the staging index
commit: Record changes into the local
repository
rebase: Used to edit commits or join commits
into a single commit to cleanup tree history
9. GIT most common commands
fetch: Get commits from a remote (this does
not merge the commits or apply the commits to
working copy)
merge: Merge the commits of a branch on a
remote
cherry-pick: Merge a specific commit from a
remote
pull: Merge the changes from the origin
repository on the current branch
push: Push changes to a remote repository
10. GIT most common commands
rm: Deletes a file from the staging index (not
deletes the physical file by itself)
reset: Remove file from index or Reset
(Rollback) HEAD to a specific commit
revert: Revertir un commit (not a file)
diff: Shows differences between commits or
branches
show: Shows commit details (user, time and
changes)
log: Shows commit history
11. GIT Configuration
git-config: Used to configure repository settings (/git/config
file) or global settings (.gitconfig). For example:
git config --global user.name "Username"
will get the following result into .gitconfig file generally
located in your home directory
[user]
...
name = Username
...
12. Git Configuration
These are the basic settings that every developer should set in their local
environments:
git config --global user.name "Username"
git config --global user.email "username@devsu.com"
Also these are useful commands that will display output of some commands in
a better way
git config --global color.branch auto
git config --global color.diff auto
git config --global color.interactive auto
git config --global color.status auto
git config --global format.pretty oneline
13. GIT Configuration
In a similar way we can set a specific repository
configuration. For example, to set the remote origin as the
default remote for the branch master
git config branch.master.remote origin
will get the following result into .git/config file
[branch "master"]
...
remote = origin
...
14. Create a new repository
We can create a new repository from any directory where
we have write permissions. It is as simple as running the
command
git init
In general, the origin or any repo that you want to make
public must be a bare repository, in which case we will run
git init --bare
15. Clone a existing repository
GIT supports different protocols to clone. Here are some
examples:
git clone git@github.com:ericmaster/liquidsoap
git clone file://localhost/srv/git/liquidsoap
git clone ssh://ericmaster@192.168.1.245/srv/git/liquidsoap
The first approach we will tipically use to clone from a
public repository. Second approach we will tipically use to
clone from a local machine. Third approach we will tipically
use to clone a repo from a server where we have an
account set up.
16. GIT Workflow
A tipical workflow of a git repository involves the following
commands
git diff (see what is about to be commited)
git add file1 file2 file3 (adding files to the index)
git status (verify all files have been included in the staging index)
git commit -m 'some message about this commit' (record commit in the
repository)
You may skip "git add" if you want to add all modified files
(not new created files) by running:
git commit -a -m 'some message about this commit'
17. Checking the status
This is the info that we may get when we run the "git status"
command:
This line will tell us in which branch we are
#On branch development
This line will tell us that the current branch has 12 more commit objects than what it has in its origin.
#Your branch is ahead of 'origin/development' by 12 commits.
After push to the origin git status will basically say that everything is ok by the following output:
#nothing to commit (working directory clean)
This line will tell us that the branch at the origin branch has 10 more commit objects than what is in the
current branch, this may indicate that we need to pull to update our working copy
#Your branch is behind of 'origin/development' by 10 commits.
In many cases we will have the following output:
#Your branch and 'origin/development' have diverged,
#and have 14 and 30 different commit(s) each, respectively.
This tells us that there are 14 commit objects in the current branch in your local repository that have
not been pushed yet and 30 commit objects in the same branch at its origin that has not been pulled
yet.
18. Checking the status
These lines will tell us which files have been added to the index
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: file1
These lines will tell us which files have been modified but not added to the index
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working
directory)
#
# modified: file1
These lines will tell us that there are files that are not under tracking
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# filex
19. Working with branches
Suppose that you have been assigned a task to create a new user profile page.
You can create a separate branch for this new feature by using:
git branch feature_user_profile
To list all branches use
git branch (to list all branches in the current repository)
git branch -a (to list all branches including branches in tracked remotes)
Output of the first command should be
feature_user_profile
master*
* Indicates our current branch
20. Working with branches
Besides using checkout to discard changes of a file you can use it to switch
branches
git checkout feature_user_profile
Now you can make some modifications to your working copy, add those
changes to the index and commit, then switch back to the master branch. You
will notice that any change you make on feature_user_profile branch will not
affect the master branch. Once we are done with the feature we can merge
those changes back to the master branch (make sure your current branch is the
master branch).
git merge feature_user_profile
git cherry-pick commit_id (in case you just need to merge a specific
commit)
21. Working with remotes
In a real case, you will have to work in a feature with multiple developers (each
with its own working copy). At some point you will need to synchronize your
code with the rest of the developers.
You could push your code to the origin so others can pull but we do not want to
do that because other developers' code might be affected by a work in
progress, specially if you are pushing to the "master" branch or the main branch
of development.
AVOID
ORIGIN ORIGIN
DEV1 DEV2 DEV3 DEV1 DEV2 DEV3
So you will need to track each developer repository as a remote. To do this you
need to add the remote into your config.
22. Working with remotes
First we add the remote with the following command (typically we will identify
each remote by the owners name or a nickname easy enough to remember in
this case the remote name will be "developer2")
git remote add developer2 ssh://ericmaster@devsuserver.
com/home/developer2/
git config remote.developer1.fetch +refs/heads/*:refs/remotes/developer2/*
which will add the following entry in the .git/config file. First line adds the remote
and assigns a url so we can know where it is. Second line allows us to track the
heads of the different branches of the remote.
[remote "developer2"]
url = ssh://ericmaster@devsuserver.com/home/developer2/
fetch = +refs/heads/*:refs/remotes/developer2/*
23. Working with Remotes
Now we have everything we need to merge changes with a remote repository.
First we need to get all the commit objects from the remote repo into our local
repo with the following command:
git fetch developer2
git fetch --all (if you want to get all the commit objects from all the
remotes you are tracking)
Next thing we want to do is to merge the changes into our working copy, for this
we can use the merge command
git merge developer2/feature_user_profile
git pull developer2/feature_user_profile (actually git pull is a shorthand
for git fetch and git merge)
If everything goes right, we should see a message telling us how many files
were changed and how many line insertions/deletions were made
35 files changed, 2334 insertions(+), 309 deletions(-)
24. Dealing with conflicts
At some point you will have to deal with conflicts when you get a message like
this after running a pull or merge command
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.
There are many ways you can deal with conflicts, as well as there are many
tools that will help you to deal with this. When a conflict occurs, your local repo
will not be updated and the index will be left in a special state until you resolve
the conflict and push the changes. If you run git status you will see that
successfully merged files are already added to the staging index ready to be
committed while conflicted files will show as
# both modified: file.txt
Both modified means that there are modifications of the file in your local branch
as well as the remote branch that could not be automatically merged
25. Dealing with conflicts
To resolve conflicts you need to edit the file and look for the following tags
<<<< HEAD
//Here goes the local code
====
//Here goes the incoming remote code
>>>> commit_id
There are some tools like merge-tool which can be integrated with git command
line that will display in a split screen showing the local code in the left and the
remote code in the right. You can also look at the conflicts with:
git diff file.txt
Clarity and good documentation of the code are determining factors in the
process of resolving a commit.
26. Dealing with conflicts
Many times you will be able to resolve the conflicts by simple inspection of the
code. For example, the HEAD of your branch might have a condition like this
if(c1 && c2){...}
while the remote commit might have something like
if(c1 && c3){...}
most likely is that this commit could be solved, depending on the case, by
changing the conflicted piece to
if(c1 && c2 && c3){...} or
if(c1 && c2 || c1 && c3){...}
27. Dealing with conflicts
If the case is more complex, you can run the following command get the
commit details including the author and its descriptive message and take some
decision based on that:
git show commit_id
Sometimes, if we cannot solve the conflict by ourselves we can contact the
developer author of the commit to get some more information that might help us
to resolve the conflict. We might even decide that is better to keep "our" or
"their" modifications only. In the first case we will use the following command:
git checkout --ours file.txt
otherwise we can keep their changes
git checkout --theirs file.txt
28. Dealing with conflicts
After you have resolved the conflict, you need to add the resolved file to the
staging index and commit.
In the case you get stuck with the conflict and just decide to get back to the
state before the merge you can use the following command
git reset --hard HEAD
but if you already commited the merge you can use
git reset --hard ORIG_HEAD
when we add the --hard option we are discarding any changes made to index
(not the working directory) while --soft option leaves the index intact
29. Checking the commit history
Whenever you find a problem or want to check for a code that was removed
some time ago, you can always check the logs to see the commit history in the
current branch:
git log
git log file.txt (to check the log for a specific file)
The git log command has many options to output the data you need in a better
way. Check the documentation for a better explanantion of these options http:
//schacon.github.com/git/git-log.html.
You can also find which user edited a specific line of a file through the following
command
git blame
30. Creating aliases
There are common aliases used in git repositories. For example I can add a
shorthand for checkout with
git config --global alias.co checkout
Also there are other common aliases that are very useful. You can add them
through the git config command or write them directly into .gitconfig file
[alias]
co = checkout
ci = commit
st = status
br = branch
hist = log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short
type = cat-file -t
dump = cat-file -p
31. Creating Tags
The git tag command creates a static branch that we can
refer later (or revert if necessary)
git tag -a v1.2 -m 'version 1.2'
To display the tags just type
git tag
32. Ignoring Files
In most of projects there are special files, typically configuration files or content
files that are specific to the local working copy where they exists. We do not
want to track these files through git. To prevent these to show up in the staging
index just add the file names to a special file named .gitignore. This special file
will typically look like this:
# Ignore any file named foo.txt.
foo.txt
# Ignore (generated) html files,
*.html
# except foo.html which is maintained by hand.
!foo.html
# Ignore objects and archives.
*.[oa]
If you are already tracking a file through git you can remove it by running the
following command and the commit
# git rm --cached foo.txt
33. Rebasing
git rebase can be used to cleanup the branches tree history. Instead of merging
your main development branch into your current feature work branch you
rebase the development branch:
git rebase development
git rebase -i development (to interactively add commits)
which will discard your commit(s) and reapply them as patches after the HEAD
of the development branch. If in any case you get a conflict, use the following
command after resolving the conflict
git rebase --continue
also you may cancel the rebase process by
git rebase --abort
34. Stashing changes
In any project, you may often want to pull to update your working copy but do
not want to commit your code yet. Git will not let you pull if the incoming commit
(s) belongs to a file that you are editing. In this case you can temporarily save
your changes and "revert" to the HEAD of your repo with the following
command
git stash
This is also useful if you need to perform a quick fix without needing to commit
or discard the changes of your current task, or even create a new branch. Once
you are done with the changes, just run the following command to get your
save changes back
git stash pop
35. Hooks
GIT allows you to implement hooks to execute certain
events occur in your repo. For example you might need to
change some setting files in your working directory before
you switch to another branch. This can be implemented in a
hook.
Under the .git/hooks directory you can find files that you
can edit to perform processing on determined events. For
example you can use the file
.git/hooks/post-commit
to notify to some system that a commit was made
36. GIT Tools
Set up public repositories
● gitosis
● gitolite (recommended by the community, see http://www.llamabyte.
com/2011/upgrading-to-gitolite-from-gitosis/ for advantages)
Merge tools:
● Open Source
○ kdiff3
○ tkdiff
○ xxdiff
● Free from a commercial vendor
○ SourceGear DiffMerge
○ FileMerge/opendiff
○ Perforce Visual Merge Tool (P4Merge)
● Commercial
○ Araxis Merge (Windows | Mac OS X)
○ Beyond Compare
○ Guiffy SureMerge
37. Common issues
I deleted a file how to commit that change to my local repo?
There are two options:
git add -A .
git commit -m
or
git commit -a -m.
Note: git commit -a -m does NOT add new created files to the staging index
38. Common issues
I made a commit but I want to correct the message or forgot to add my
username or email
To correct the message of the last commit use:
git commit --amend -m 'correct message'
To correct the message of commit previous to the HEAD commit you can use:
git rebase -i commit_id^
then change "pick" to "edit" in the interactive mode for commit_id, make the
changes and then run
git commit --amend
git rebase continue
39. Common issues
I need to revert a commit given by a specific commit_id
Just run the following command
git revert commit_id
this will revert the commit object and commit the revert.
Add the --no-commit option to leave the changes in the
staging index for any further modification before commit
Note: this might lead to conflicts if the subsequent commits
have overlapped changes.
40. Common issues
I need to work in team with a developer who created a new branch for a
specific feature. How do I clone that branch over my current working
copy?
After adding the remote "developer", just run the following command
git checkout --track -b new_feature developer/new_feature
this will create the new repo and add the necessary branch settings in the .
git/config file