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.
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Introduction to Git Basics
1. commit e1c7ae40152ee163f477863215e77917a863faa3
Author: Roy Lee <roylee17@gmail.com>
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 <roylee17@gmail.com>
1
2. X
Y Z
We have a small project,
and we want to manage it with GIT.
2
3. X
empty... stage
working tree
Y Z
First, we create a git repository with „git init‟
This creates a .git directory, which stores the whole git stuff,
and initializes the stage (a.k.a. index or cache)
3
4. staging
T1
X X T2
Y Z Y Z
working tree stage
Then we add the working tree to the stage.
This is called „staging‟.
4
5. Initial
Commit
T1 T1
X
X T2 X T2
Y Z
Y Z Y Z
working tree stage database
Finally, commit the stage to the database.
That‟s it! You now have a GIT repository
5
6. Initial
Commit
T1 T1
X
X T2 X T2
Y Z
Y Z Y Z
working tree stage 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”
6
7. HEAD
Initial master
Commit
T1 T1
X’
X T2 X T2
Y Z
Y Z Y Z
working tree stage database
Now, we edit some files
7
8. HEAD
Initial master
Commit
T1’ T1
X’
X’ T2 X T2
Y Z
Y Z Y Z
working tree stage database
Stage the changes.
8
9. HEAD
Initial Another master
Commit Commit
T1’ T1 T1’
X’
X’ T2 X T2 X’ T2
Y Z
Y Z Y Z Y Z
working tree stage database
And commit the stage to the database.
9
10. HEAD
Initial Another master
Commit Commit
T1’ T1 T1’
X’
X’ T2 X T2 X’ T2
Y Z
Y Z Y Z Y Z
working tree stage database
Changes committed to or checked out from database
must get into the staging area
10
11. HEAD
Initial Another master
Commit Commit
T1’ T1
T1’
X’
X’ T2 X T2
X’ T2
Y’ Z’
Y Z Y Z
Y Z
working tree stage database
This time we have two files changed for
two different things since the last commit.
11
12. HEAD
Initial Another master
Commit Commit
T1’’ T1
T1’
X’
X’ T2’ X T2
X’ T2
Y’ Z’
Y’ Z Y Z
Y Z
working tree stage database
Rather than committing them “all at once”,
we can do this incrementally by only staging
“partial” of the changes. 12
13. HEAD
git diff git diff --staged
Initial Another master
Commit Commit
T1’’ T1
T1’
X’
X’ T2’ X T2
X’ T2
Y’ Z’
Y’ Z Y Z
Y Z
working tree stage database
# Diff the working tree and the stage
$ git diff
# Diff the stage and the HEAD commit
$ git diff --staged
13
14. HEAD
Commit I Commit A master
T1’’ T1 T1’
X’
X’ T2’ X T2 X’ T2
Y’ Z’
Y’ Z Y Z Y Z
working tree stage database
$ git status
# Changes to be committed: staged changes
# (use "git reset HEAD <file>..." to unstage)
#
# modified: T/Y
#
# Changed but not updated: unstaged changes
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: T/Z
14
15. HEAD
Initial Another Another master
Commit Commit Commit
T1’’ T1
T1’
T1’’
X’
X’ T2’ X T2
X’ T2
X’ T2’
Y’ Z’
Y’ Z Y Z
Y Z
Y’ Z
working tree stage database
Commit the stage to the database.
15
16. HEAD
Initial Another Another master
Commit Commit Commit
T1’’ T1
T1’
T1’’
X’
X’ T2’ X T2
X’ T2
X’ T2’
Y’ Z’
Y’ Z Y Z
Y Z
Y’ Z
working tree stage database
# 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
16
17. HEAD
Initial Another Another master
Commit Commit Commit
T1’’ T1
T1’
T1’’
X’
X’ T2’ X T2
X’ T2
X’ T2’
Y’ Z’
Y’ Z Y Z
Y Z
Y’ Z
working tree stage database
$ 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]
17
18. 1
master HEAD HEAD
3 2
Commit I Commit A master
T1 T1 T1’
X
X T2 X T2 X’ T2
Y Z
Y Z Y Z Y Z
working tree stage database
# (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)
18
19. branch A HEAD
2 1
Commit I Commit A master
T1 T1 T1’
X
X T2 X T2 X’ T2
Y Z
Y Z Y Z Y Z
working tree stage 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)
19
20. There are four types of object in the database.
tag Tag
commit v0.01
Initial Another
tree
Commit Commit
T1 T1’
X T2 X’ T2
blob Y Z Y Z
20
21. Every object has an unique ID calculated by
taking the SHA1 hash of its contents.
tag Tag
commit v0.01
Initial Another
tree
Commit Commit
T1 T1’
X T2 X’ T2
blob Y Z Y Z
21
22. Objects are compressed and uniquely stored as
loose objects or packfiles.
tag Tag tag Tag
commit v0.01
commit v0.01
Initial Another Initial Another
tree tree
Commit Commit Commit Commit
T1 T1’ T1 T1’
X T2 X’ T2 X T2 X’
blob Y Z Y Z blob Y Z
delta
Similar contents could be stored as deltas. 22
23. Another Commit
HEAD
I A B C master
A branch can be seen as a chain of commits.
A branch name is simply a reference to the top most commit.
A default branch master is created when you „clone‟ or „init‟ a git repo.
23
24. Another Commit
HEAD
XY
I A B C master
JK bak1
# 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 HEAD
25a0510 log messages for C
7731a6d log messages for B
d2e8d8a log messages for A
a8272ea log messages for I
# Creating branches on the previous commits
$ git branch d2e8d8a JK
$ git branch 7731a6d XY
24
25. Another Commit
HEAD
XY
I A B C master
JK bak1
# 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/JK
3bf7886705b4ea7189f046fa5258fdf6edcdbe23
$ cat proj/.git/HEAD # The HEAD usually (but not necessarily) points to another pointer
ref: refs/heads/master
25
26. A Branch name or a commit ID suffixed
with a ^N symbol refers to its N-th parent commit.
Similarly, a ~N suffix refers to the previous N commit.
XY^
HEAD^ XY
master~1
X Y
XY^^ HEAD
XY~2
I A B C master
26
27. Another Commit
Switching between branches with ‟git checkout‟.
The HEAD pointer refers to the current branch.
XY
X Y
HEAD
I A B C master
J K
jk
JK
27
28. 1
branch A HEAD HEAD
3 2
Commit I Commit A master
T1 T1 T1’
X
X T2 X T2 X’ T2
Y Z
Y Z Y Z Y Z
working tree stage database
# 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>
28
29. 1
branch A HEAD HEAD
2
Commit I Commit A master
T1’ T1 T1’
X’
X’ T2 X T2 X’ T2
Y Z
Y Z Y Z Y Z
working tree stage database
# 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.)
29
30. X Y XY
I A B C master
J K JK
We‟d like to rebase JK and XY branches onto master
like this
X Y X Y XY
I A B C master
J K JK HEAD
J K
30
31. Let‟s begin with rebasing XY onto master
X Y XY
I A B C master HEAD
J K JK
31
32. Find the common ancestor commit of both branches
X Y XY
I A B C master HEAD
J K JK
32
33. Checkout the tip commit of the target branch
X Y XY HEAD
I A B C master
J K JK
33
34. Apply the commits to the rebasing branch
X Y X Y XY HEAD
I A B C master
J K JK
34
35. Now, let‟s rebase JK onto master
X Y X Y XY HEAD
I A B C master
J K JK
35
36. Find the common ancestor commit of both branches
X Y X Y XY
I A B C master
J K JK HEAD
36
37. Checkout the tip commit of the target branch
X Y X Y XY
I A B C master
J K JK HEAD
37
38. Apply the commits to the rebasing branch
X Y X Y XY
I A B C master
J K J K JK HEAD
38
39. Done!
X Y X Y XY
I A B C master
J K J K JK HEAD
39
40. # The trace of the HEAD
I $ git reflog
d5462a0 HEAD@{0}: rebase finished: returning to refs/heads/JK
A d5462a0 HEAD@{1}: rebase: log messages for K
a024870 HEAD@{2}: rebase: log messages for J
6103ef9 HEAD@,3-: checkout: moving from JK to 6103…
5 J 016564d HEAD@{4}: commit: log messages for K
25a0510 HEAD@{5}: commit: log messages for J
4 K B
old_JK
# Browse the log
$ git log --abbrev-commit --pretty=oneline HEAD@{4}
016564d log messages for K
25a0510 log messages for J
C 3
d2e8d8a log messages for A
a8272ea Initial
J 2 X
# Rescuing the commit with a “reference”
HEAD
K 0&1 Y $ git branch HEAD@{4} old_JK
JK
40
41. Apply the commit C to the JK branch with ‘git cherry-pick’
I A B C master
J K JK HEAD
I A B C master
J K C’ JK HEAD
41
42. Revert the commit A with ‘git revert’
I A B C master
J K JK HEAD
I A B C master
J K A-1 JK HEAD
42
43. alice server bob
I HEAD
A master
# Suppose we have a proj host on my-server.com
43
44. alice server bob
I I HEAD
HEAD origin/HEAD
A A master
master origin/master
# Alice clones it to her local machine.
alice $ git clone alice@my-server.com:/var/git/proj.git
44
45. alice server bob
I I HEAD I HEAD
HEAD origin/HEAD origin/HEAD
A A master A master
master origin/master origin/master
# And Bob also clones it on his machine.
bob $ git clone bob@my-server.com:/var/git/proj.git
45
46. alice server bob
I I HEAD I HEAD
origin/HEAD origin/HEAD
A A master A master
origin/master origin/master
J
HEAD
K
master
# Alice commits to her local branch.
alice $ git commit -a -m “message for J”
alice $ git commit -a -m “message for K”
46
47. alice server bob
I I HEAD I
origin/HEAD origin/HEAD
A A master A
origin/master origin/master
J
HEAD
K HEAD
master
B master
# Bob also commits to his local branch.
bob $ git commit -a -m “message for B”
47
48. alice server bob
I I HEAD I
origin/HEAD origin/HEAD
A A master A
origin/master origin/master
J
HEAD
K HEAD HEAD
master
origin/HEAD
B master B master
origin/master
# Bob pushes his commit to the server with either one of the following commands.
bob $ git push blob@my-server.com:/var/git/proj.git HEAD:master
bob $ git push origin HEAD:master
bob $ git push
48
49. alice server bob
I I I
origin/HEAD
A A A
origin/master
J
HEAD
K HEAD HEAD
master
origin/HEAD
B master B master
origin/master
# Then pushes her local commits to the server with either one of the following commands.
alice $ git push alice@my-server.com:/var/git/proj.git HEAD:master
alice $ git push origin HEAD:master
alice $ git push
49
50. alice server bob
I I I
origin/HEAD
A A A
origin/master
J
HEAD
K HEAD HEAD
master
origin/HEAD
B master B master
origin/master
# But the push fails with the following message
To alice@my-server.com:/var/git/proj.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to ‘alice@my-server.com:/var/git/proj.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the 'Note about
fast-forwards' section of 'git push --help' for details.
50
51. alice server bob
I I I
origin/HEAD
A A A
origin/master
J
HEAD
K HEAD HEAD
master
origin/HEAD
origin/HEAD
B B master B master
origin/master
origin/master
# Alice updates her local repository with either one of the following commands
alice $ git fetch alice@my-server.com:/var/git/proj.git
alice $ git fetch origin
51
52. alice server bob
I I I
A A A
J
HEAD
K HEAD HEAD
master
origin/HEAD
origin/HEAD
B B master B master
origin/master
origin/master
J
HEAD
K # Alice rebases his branch onto the origin/master
alice $ git rebase origin/master master
master First, rewinding head to replay your work on top of it...
Applying: message for J
Applying: message for K
52
53. alice server bob
I I I
A A A
HEAD HEAD
origin/HEAD
origin/HEAD
B B master B master
origin/master
origin/master
J J HEAD
HEAD
master
K origin/master K
master
origin/HEAD # Alice pushes his commits to the server.
alice $ git remote add bob alice@bob-pc:/var/git/public/proj.git
alice $ git fetch bob
53
54. alice server bob
I I I
A A A
HEAD
origin/HEAD
B B B master
origin/master
J J HEAD X master
HEAD
master HEAD
K origin/master K
master
origin/HEAD # Bob commits another changes to his local branch
bob $ git commit -a -m “messages for X”
54
55. alice server bob
I I I
A A A
J
K
origin/HEAD
bob/HEAD
B B B HEAD
origin/master
bob/master
J X J HEAD X master
HEAD
master
K origin/master K
master
origin/HEAD # Alice adds Bob’s repository as another remote repository.
alice $ git remote add bob alice@bob-pc:/var/git/public/proj.git
alice $ git fetch bob
55
56. # List remote repositories
I alice $ git remote -v
origin alice@my-server.com:/var/git/public/proj.git (fetch)
origin alice@my-server.com:/var/git/public/proj.git (push)
A bob alice@bob-pc:/var/git/public/proj.git (fetch)
bob alice@bob-pc:/var/git/public/proj.git (push)
J
# The references can be found at .git/refs/
alice $ tree proj/.git/refs
K proj/.git/refs/
├─ heads
│ └── master
bob/HEAD
B ├─ remotes
│ ├─ bob
bob/master │ │ ├── HEAD
J X │ │ └── master
│ └─ origin
HEAD
│ ├── HEAD
K origin/master
│ └── master
master └─ tags
origin/HEAD
56
58. # Then pushes her local commits to the server with either one of the following commands.
# ~/.gitconfig
[user]
name = Your Name
email = Your E-mail Address
[color]
branch = auto
diff = auto
status = auto
[alias]
timeline = log --oneline --dec --branches
l = log --dec
br = branch
st = status -s
stu = status -s -uno
co = checkout
[core]
filemode = false
58
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 variable
export PS1='[e[1;32m]u@[e[1;33m]h[e[1;34m] w$(__git_ps1 "[e[1;36m] <%s>[e[1;34m]") $[e[m] '
59
60. 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