introduction to git basics
DESCRIPTION
Introduction to the basic concept of git, including 1) working directory and stage(previously called cache or index), 2) Branch manipulation, and 3) Working with remote repositories.TRANSCRIPT
commit e1c7ae40152ee163f477863215e77917a863faa3
Author: Roy Lee <[email protected]>
Date: Sun Oct 14 12:10:30 2012 -0700
git: Introduction to GIT basics
Working tree, stage and database
Manipulating branches
Collaborating with remote repositories
Signed-off-by: Roy Lee <[email protected]>
1
2
Y Z
X
We have a small project,
and we want to manage it with GIT.
3
empty... stage
Y Z
X
working tree
First, we create a git repository with „git init‟
and initializes the stage (a.k.a. index or cache)This creates a .git directory, which stores the whole git stuff,
4
Y Z
X
Y Z
T2X
T1
stageworking tree
Then we add the working tree to the stage.
This is called „staging‟.
staging
5
Y Z
X
Y Z
T2X
T1
Y Z
T2X
T1
Initial Commit
Finally, commit the stage to the database.
stageworking tree database
That‟s it! You now have a GIT repository
6
Y Z
X
Y Z
T2X
T1
Y Z
T2X
T1
Initial Commit
stageworking tree database
$ git init # Initialize the git database (the .git directory)$ git add [ <paths> | <pattern> | . ] # Add files to the stage
# Commit the stage to the database with a specified log message# (without the “-m” options, git prompts the editor for asking log message)$ git commit -m “Initial commit”
7
Y Z
X’
Y Z
T2X
T1
Y Z
T2X
T1
Initial Commit
Now, we edit some files
stageworking tree database
HEAD
master
8
Y Z
X’
Y Z
T2X’
T1’
Stage the changes.
stageworking tree database
Y Z
T2X
T1
Initial Commit
HEAD
master
9
Y Z
X’
Y Z
T2X’
T1’
And commit the stage to the database.
Y Z
T2X’
T1’
Another Commit
stageworking tree database
Y Z
T2X
T1
Initial Commit
HEAD
master
10
Y Z
X’
Y Z
T2X’
T1’
Changes committed to or checked out from database
Y Z
T2X’
T1’
Another Commit
stageworking tree database
Y Z
T2X
T1
Initial Commit
HEAD
master
must get into the staging area
11
Y’ Z’
X’
Y Z
T2X’
T1’
stageworking tree database
two different things since the last commit.
Y Z
T2X
T1
Initial Commit
Y Z
T2X’
T1’
Another Commit
HEAD
master
This time we have two files changed for
12
Y’ Z’
X’
Y’ Z
T2’X’
T1’’
we can do this incrementally by only staging
stageworking tree database
Y Z
T2X
T1
Initial Commit
Y Z
T2X’
T1’
Another Commit
HEAD
master
Rather than committing them “all at once”,
“partial” of the changes.
13
Y’ Z’
X’
Y’ Z
T2’X’
T1’’
stageworking tree database
Y Z
T2X
T1
Initial Commit
Y Z
T2X’
T1’
Another Commit
HEAD
master
# Diff the working tree and the stage$ git diff
# Diff the stage and the HEAD commit$ git diff --staged
git diff git diff --staged
14
Y’ Z’
X’
Y’ Z
T2’X’
T1’’
Y Z
T2X
T1
Commit I
Y Z
T2X’
T1’
Commit A
stageworking tree database$ git status# Changes to be committed:# (use "git reset HEAD <file>..." to unstage)## modified: T/Y## Changed but not updated:# (use "git add <file>..." to update what will be committed)# (use "git checkout -- <file>..." to discard changes in working directory)## modified: T/Z
HEAD
master
staged changes
unstaged changes
15
Y’ Z’
X’
Y’ Z
T2’X’
T1’’
stageworking tree database
Y Z
T2X
T1
Initial Commit
Y Z
T2X’
T1’
Another Commit
Y’ Z
T2’X’
T1’’
Another Commit
HEAD
master
Commit the stage to the database.
16
Y’ Z’
X’
Y’ Z
T2’X’
T1’’
stageworking tree database
Y Z
T2X
T1
Initial Commit
Y Z
T2X’
T1’
Another Commit
Y’ Z
T2’X’
T1’’
Another Commit
HEAD
master
# Moving a tracked file around involves not only the working tree, but also the stage.$ mv T/Y Y$ git add Y$ git rm T/Y# ‘git mv’ simplify this with a single step.$ git mv T/Y Y
17
Y’ Z’
X’
Y’ Z
T2’X’
T1’’
stageworking tree database
Y Z
T2X
T1
Initial Commit
Y Z
T2X’
T1’
Another Commit
Y’ Z
T2’X’
T1’’
Another Commit
HEAD
master
$ git log # Browse the commit history$ git log --stat # Show diffstat$ git log -p # Show the logs in ‘patch format’$ git log -n2 # Show no more than two commits$ git log a..b # Show the commits between (a, b]
18
Y Z
X
Y Z
T2X
T1
Y Z
T2X
T1
Commit I
Y Z
T2X’
T1’
Commit A
stageworking tree database
1
# (1) Adjust the HEAD pointer (and the pointer pointed by it) to the <commit># (2) Reset the stage to <commit># (3) Checkout the files from the stage to working tree$ git reset --soft [<commit>] # (1), $ git reset --mixed [<commit>] # (1) + (2), this is the default behavior$ git reset --hard [<commit>] # (1) + (2) + (3)
23
HEAD HEAD
master
master
19
Y Z
T2X
T1
Commit I
Y Z
T2X’
T1’
Commit A
stageworking tree database
# To restore the file contents from the cache to the working tree, use$ git checkout <paths> # (2)
# To retrieve the file contents from a specific commit, use$ git checkout <commit> -- <paths> # (1) + (2)
12
branch A HEAD
master
Y Z
X
Y Z
T2X
T1
20
There are four types of object in the database.
Y Z
T2X
T1
Initial Commit
Y Z
T2X’
T1’
Another Commit
Tagv0.01
blob
tree
tagcommit
21
Every object has an unique ID calculated by
taking the SHA1 hash of its contents.
Y Z
T2X
T1
Initial Commit
Y Z
T2X’
T1’
Another Commit
Tagv0.01
blob
tree
tagcommit
22
Objects are compressed and uniquely stored as
Y Z
T2X
T1
X’
T1’
blob
treeInitial
CommitAnother Commit
Tagv0.01
tagcommit
Y Z
T2X
T1
Initial Commit
Y Z
T2X’
T1’
Another Commit
Tagv0.01
blob
tree
tagcommit
delta
Similar contents could be stored as deltas.
loose objects or packfiles.
23
Another Commit
A default branch master is created when you „clone‟ or „init‟ a git repo.
A branch can be seen as a chain of commits.
A branch name is simply a reference to the top most commit.
I A B C
HEAD
master
24
Another Commit
# Creating a new branch on the current commit.$ git branch bak1
# Showing the commit history in a compact format $ git log --abbrev-commit --pretty=oneline HEAD25a0510 log messages for C7731a6d log messages for Bd2e8d8a log messages for Aa8272ea log messages for I
# Creating branches on the previous commits$ git branch d2e8d8a JK$ git branch 7731a6d XY
I A B C
XY
JK
HEAD
master
bak1
25
Another Commit
# Active references are located in the .git/refs/ while inactive references might be packed in .git/packed-refs$ tree proj/.git/refs.git/refs/├─heads│ ├── JK│ ├──master│ └──XY└─ tags
└── v0.01$ cat proj/.git/refs/heads/JK3bf7886705b4ea7189f046fa5258fdf6edcdbe23$ cat proj/.git/HEAD # The HEAD usually (but not necessarily) points to another pointerref: refs/heads/master
I A B C
XY
JK
HEAD
master
bak1
26
Similarly, a ~N suffix refers to the previous N commit.
I A B
X Y
C
HEAD^master~1XY^^XY~2
with a ^N symbol refers to its N-th parent commit.
XY^
A Branch name or a commit ID suffixed
XY
HEAD
master
27
Another Commit
I A
jkJ
B
K
X Y
C
The HEAD pointer refers to the current branch.
Switching between branches with ‟git checkout‟.
XY
JK
HEAD
master
28
Y Z
X
Y Z
T2X
T1
Y Z
T2X
T1
Commit I
Y Z
T2X’
T1’
Commit A
stageworking tree database
1
# Switching between branches is also done by ‘git checkout’ without given the <paths># Recall that we used the ‘git checkout *tree-ish+ <paths>’ for checking out the content of a specified commit?
# This time the ‘git checkout’ command switches branches by updating the stage, working tree, and HEAD $ git checkout <tree-ish>
2
HEADbranch A HEAD
master3
29
Y Z
X’
Y Z
T2X’
T1’
Y Z
T2X
T1
Commit I
Y Z
T2X’
T1’
Commit A
stageworking tree database
1
# In cases where you have local changes, git compares your HEAD and TARGET commits for those modified files.# If the contents of the modified files on both commits# match : the local changes are preserved, and the checkout succeed# do not match : the checkout will be refused to avoid overwrite those local changes
(Thanks to Jeff King and Junio Hamano for their elaborations on how this works.)
2
HEADbranch A HEAD
master
30
I BA
J K
X Y
C
JK
XY
master
We‟d like to rebase JK and XY branches onto masterlike this
I BA
J K
X Y
C master
X Y XY
J K JK HEAD
31
I BA
J K
X Y
C
JK
XY
master HEAD
Let‟s begin with rebasing XY onto master
32
I BA
J K
X Y
C
JK
XY
master HEAD
Find the common ancestor commit of both branches
33
I BA
J K
X Y
C
JK
master
XY HEAD
Checkout the tip commit of the target branch
34
I BA
J K
C
JK
master
X Y XYX Y HEAD
Apply the commits to the rebasing branch
35
I BA
J K
C
JK
master
X Y XYX Y HEAD
Now, let‟s rebase JK onto master
36
I BA
J K
C
JK
master
X Y XYX Y
HEAD
Find the common ancestor commit of both branches
37
I BA
J K
C
JK
master
X Y XYX Y
HEAD
Checkout the tip commit of the target branch
38
I BA
J K
X Y
C master
X Y XY
J K JK HEAD
Apply the commits to the rebasing branch
39
I BA
J K
X Y
C master
X Y XY
J K JK HEAD
Done!
40
I
A
J
K
C
J
K
X
HEAD
JK
# The trace of the HEAD$ git reflogd5462a0 HEAD@{0}: rebase finished: returning to refs/heads/JKd5462a0 HEAD@{1}: rebase: log messages for Ka024870 HEAD@{2}: rebase: log messages for J6103ef9 HEAD@,3-: checkout: moving from JK to 6103…016564d HEAD@{4}: commit: log messages for K25a0510 HEAD@{5}: commit: log messages for J
# Browse the log$ git log --abbrev-commit --pretty=oneline HEAD@{4}016564d log messages for K25a0510 log messages for Jd2e8d8a log messages for Aa8272ea Initial
# Rescuing the commit with a “reference”$ git branch HEAD@{4} old_JK
old_JK
Y
B
0 & 1
2
3
4
5
41
I A B
J K
C
C’
Apply the commit C to the JK branch with ‘git cherry-pick’
JK HEAD
master
I A B
J K
C
JK HEAD
master
42
I A B
J K
C
A-1
Revert the commit A with ‘git revert’
JK HEAD
master
I A B
J K
C
JK HEAD
master
43
I
A
HEAD
master
# Suppose we have a proj host on my-server.com
alice server bob
44
I
A
I
Aorigin/HEAD
origin/master
HEAD
master
HEAD
master
# Alice clones it to her local machine.alice $ git clone [email protected]:/var/git/proj.git
alice server bob
45
I
A
I
AHEAD
master
I
Aorigin/HEAD
origin/master
HEAD
master
origin/HEAD
origin/master
HEAD
master
# And Bob also clones it on his machine.bob $ git clone [email protected]:/var/git/proj.git
alice server bob
46
I
A
I
A
I
A
J
K
HEAD
master
HEAD
master
HEAD
master
origin/HEAD
origin/master
origin/HEAD
origin/master
# Alice commits to her local branch.alice $ git commit -a -m “message for J”alice $ git commit -a -m “message for K”
alice server bob
47
I
A
I
A
I
A
J
K
B
HEAD
master
origin/HEAD
origin/master
HEAD
master
HEAD
master
origin/HEAD
origin/master
# Bob also commits to his local branch.bob $ git commit -a -m “message for B”
alice server bob
48
I
A
I
A
I
A
J
K
BB
HEAD
master
HEAD
master
HEAD
master
origin/HEAD
origin/master
origin/HEAD
origin/master
# Bob pushes his commit to the server with either one of the following commands.bob $ git push [email protected]:/var/git/proj.git HEAD:masterbob $ git push origin HEAD:masterbob $ git push
HEAD
master
origin/HEAD
origin/master
alice server bob
49
I
A
I
A
I
A
J
K
BB
HEAD
master
HEAD
master
HEAD
master
origin/HEAD
origin/master
origin/HEAD
origin/master
# Then pushes her local commits to the server with either one of the following commands.alice $ git push [email protected]:/var/git/proj.git HEAD:masteralice $ git push origin HEAD:masteralice $ git push
alice server bob
50
I
A
I
A
I
A
J
K
BB
HEAD
master
HEAD
master
HEAD
master
origin/HEAD
origin/master
origin/HEAD
origin/master
# But the push fails with the following messageTo [email protected]:/var/git/proj.git ! [rejected] master -> master (non-fast-forward)error: failed to push some refs to ‘[email protected]:/var/git/proj.git'To prevent you from losing history, non-fast-forward updates were rejectedMerge the remote changes before pushing again. See the 'Note aboutfast-forwards' section of 'git push --help' for details.
alice server bob
51
I
A
I
A
I
A
J
K
BBB
HEAD
master
HEAD
master
HEAD
masterorigin/HEAD
origin/master
origin/HEAD
origin/master
# Alice updates her local repository with either one of the following commandsalice $ git fetch [email protected]:/var/git/proj.gitalice $ git fetch origin
origin/HEAD
origin/master
alice server bob
52
I
A
I
A
I
A
BBB
J
K
J
KHEAD
master
HEAD
master
HEAD
master
origin/HEAD
origin/master
origin/HEAD
origin/master
# Alice rebases his branch onto the origin/masteralice $ git rebase origin/master masterFirst, rewinding head to replay your work on top of it...Applying: message for JApplying: message for K
HEAD
master
alice server bob
53
I
A
I
A
I
A
BBB
J
K
J
K
HEAD
master
HEAD
master
HEAD
master
origin/master
origin/HEAD
origin/HEAD
origin/master
# Alice pushes his commits to the server.alice $ git remote add bob alice@bob-pc:/var/git/public/proj.gitalice $ git fetch bob
HEAD
masterorigin/HEAD
origin/master
alice server bob
54
I
A
I
A
I
A
BBB
J
K
J
K
XHEAD
master HEAD
master
HEAD
master
origin/HEAD
origin/master
origin/master
origin/HEAD # Bob commits another changes to his local branchbob $ git commit -a -m “messages for X”
HEAD
master
alice server bob
55
I
A
I
A
I
A
J
K
BBB
J
K
J
K
XX
bob/HEAD
bob/masterHEAD
master
HEAD
master
HEAD
master
origin/HEAD
origin/master
origin/master
origin/HEAD # Alice adds Bob’s repository as another remote repository.alice $ git remote add bob alice@bob-pc:/var/git/public/proj.gitalice $ git fetch bob
alice server bob
56
I
A
J
K
B
J
K
X
bob/HEAD
bob/master
HEAD
master
origin/master
origin/HEAD
# List remote repositoriesalice $ git remote -vorigin [email protected]:/var/git/public/proj.git (fetch)origin [email protected]:/var/git/public/proj.git (push)bob alice@bob-pc:/var/git/public/proj.git (fetch)bob alice@bob-pc:/var/git/public/proj.git (push)
# The references can be found at .git/refs/alice $ tree proj/.git/refsproj/.git/refs/├─heads│ └──master├─ remotes│ ├─bob│ │ ├──HEAD│ │ └──master│ └─origin│ ├──HEAD│ └──master └─ tags
57
$ git init$ git add$ git rm$ git mv$ git commit$ git reset$ git clean$ git stash
$ git tag$ git diff$ git status$ git log$ git show$ git grep
$ git branch$ git checkout$ git cherry-pick$ git revert$ git rebase$ git show-branch
$ git clone$ git fetch$ git push$ git pull$ git remote
58
# Then pushes her local commits to the server with either one of the following commands.# ~/.gitconfig
[user]name = Your Nameemail = Your E-mail Address
[color]branch = autodiff = autostatus = auto
[alias]timeline = log --oneline --dec --branchesl = log --decbr = branchst = status -sstu = status -s -unoco = checkout
[core]filemode = false
59
# Try out the following commands, and add it to your ~/.bash_profile or similar
# Source the bash completion script$ source /etc/base_completion.d/git
# git 1.7.X+ has split the prompt and shell completion to separate files$ source /etc/base_completion.d/git$ source /etc/base_completion.d/git-prompt.sh
# After the right scripts are sourced, __git_ps1 is available shows the current status/branch.~/git_repo/some_proj $ __git_ps1(wrk)
# You can incorporate __git_ps1 to your PS1 environment variableexport PS1='\[\e[1;32m\]\u@\[\e[1;33m\]\h\[\e[1;34m\] \w$(__git_ps1 "\[\e[1;36m\] <%s>\[\e[1;34m\]") $\[\e[m\] '
Git configurations
git config, .git/config, ~/gitconfig
Rebasing commits interactively
git rebase -i HEAD~n
Manipulate working tree and the stage interactively
git add -I
git add -p
git checkout -p
Apply patches
git am, git apply
60