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