Author : Jike Song jike.song@intel.com Last Update : 05/04/2016
* The 1st DVCS: Sun WorkShop TeamWare
- 1990's
- Larry McVoy
* BitKeeper
- Born 1998
- Larry McVoy
- Used to maintain Linux Kernel during 2002~2005
* The 2005 Storm
- Challenge from Richard Stallman et al.
- Andrew Tridgell's Reverse Engineering
- Larry: BitKeeper became unavailable
- People tried to develop alternatives:
1) Git. By Linus Torvalds, 7 April 2005
2) Mercurial. By Matt Mackall, 19 April 2005
* Initial GIT
* taken ~10 days to take shape
* the name explanation from README:
GIT - the stupid content tracker
"git" can mean anything, depending on your mood.
- random three-letter combination that is pronounceable, and not
actually used by any common UNIX command. The fact that it is a
mispronounciation of "get" may or may not be relevant.
- stupid. contemptible and despicable. simple. Take your pick from the
dictionary of slang.
- "global information tracker": you're in a good mood, and it actually
works for you. Angels sing, and a light suddenly fills the room.
- "goddamn idiotic truckload of sh*t": when it breaks
- Git is a DVCS(Distributed Version Control System)
- All copies of a repo are *exactly* the same
- Git is highly integrated with a lot of utilities in shell environment
- Always install the all-in-one package:
# apt-get install git-all
# yum install git-all
- Unfriendly for beginners
"You can do things so many ways." - Linus Torvalds on Git
"His latest cruel act is to create a revision control system
which is expressly designed to make you feel less intelligent
than you thought you were." - Andrew Morton on Linus
FYI: man 7 gitglossary
- working tree
Dirs & Files you actually see in the filesystem.
- DAG (commit object database)
The metadata of your git repository. All objects are linked
together in a DAG (Directed Acyclic Graph).
- INDEX
The cache between your working tree and DAG.
- HEAD
The newest commit of *current* branch.
To illustrate:
+----------+
| working |
| tree |----------+
+----------+ |
| |
| add |
| |
v |
+----------+ |
| INDEX | | commit -a
+----------+ |
| |
| commit |
| |
v |
+----------+ |
| commit | |
| object |<---------+
| database |
+----------+
Figure 1: How your "add/commit" works
"git add" - add your changes from working tree, to index
"git commit" - commit your changes in index, to DAG, thereby form a new HEAD
"git commit -a" - commit your changes in both working tree and index
+----------+
| working |
| tree |----------+
+----------+ |
| |
| diff |
| |
+----------+ |
| INDEX | | diff HEAD
+----------+ |
| |
| diff --cached |
| |
+----------+ |
| commit | |
| object |----------+
| database |
+----------+
Figure 2: How your "diff" works
"git diff" - diff your working tree against index
"git diff --cached" - diff your index with HEAD
"git diff HEAD" - diff your working tree with HEAD
To illustrate, let's assume that there are 2 machines:
* The machine "server", with a git repository: "warehouse",
with a branch: "twig";
* The machine "client", on which we cloned "warehouse";
+---------------+
| local branch |<---.
| "twig" |---. \
+---------------+ \ \
| \ \
| \ \
| \ \
"warehouse" on server | \ \
------------------------|---------------\-\------------------------
"warehouse" on client | \ \ push
| fetch pull \ \
| (fetch+ \ \
v merge) \ \ +--------------+
+---------------+ \ *---| local branch |
| remote branch | merge *--->| "twig" |
| "origin/twig" |-------------------->| |
+---------------+ +--------------+
remote "origin"
Figure 3: Basic remote tracking workflow
* "remote" is a git keyword, a "remote" stands for a remote
git repo (an URL);
* "origin" is not a keyword: it's simply the default
"remote" (determined at "git clone");
* "origin/twig" of client, is the mirror of "twig" of server;
* on client, "git pull" ==
git fetch + git merge origin/twig //by default
git fetch + git rebase origin/twig //pull --rebase
fast-forward
Your local branch "twig", is a proper subset of the remote branch "origin/twig".
Merging "twig" with "origin/twig" will be called "fast-forward": it simply
update "twig" to "origin/twig", not generating a merge commit.
refspec
You want to push "twig" of client, to "twig" of server:
$ git push origin twig:twig
However, if you want to push it to generate a new branch "new_twig" on server:
$ git push origin twig:new_twig
Add if you want to push a particular commit to generate a new branch:
$ git push origin master~10:new_twig
Here "origin" specifies which remote the target is;
"foo:bar" is the refspec: "foo" identifies the source revision of the client;
"bar" identifies the target branch name oof the server.
To delete the "twig" branch from server:
$ git push origin :twig
bare repo
A git repo without working tree or INDEX, only metadata.
If a repo is to be shared by multiple users, it should be bare.
git init --bare
git clone --bare
To illustrate:
origin/twig A1--A2--A3-|-B1--B2--B3
|
twig A1--A2--A3-|-[X]
[X] If you do a "git merge" here, it's a fast-forward.
origin/twig A1--A2--A3-|-B1--B2--B3
| \
| \
twig A1--A2--A3-|-C1--C2--C3--[X]--M1--
[X] If you do a "git merge" here, it's a merge, will generate
a "merge commit" M1, with 2 parents: B3 and C3.
origin/twig A1--A2--A3-|-B1--B2--B3
| \
| \
twig A1--A2--A3-|-C1--C2--C3--[X]--
|-B1--B2--B3--(C1)--(C2)--(C3)
[X] if you do a "git rebase" here, by default it will get
B1-B2-B3 at first, then take it as the new "base", and
place C1-C2-C3 upon that.
Figure 4: fast-forward, merge, rebase
FYI WIP == Work In Progress
//to save the changes
$ git stash [save]
//to list your stashes
$ git stash list
//show a particular stash
$ git stash show -p stash@{2}
//apply a particular stash
$ git stash apply stash@{2}
//drop a particular stash
$ git stash drop stash@{2}
//pop from the stash stack
//== git stash apply stash@{0} + git stash drop stash@{0}
$ git stash pop
//drop all stashes
$ git stash clear
"git bundle" backups your repository *with* metadata:
//backup your repo into a single file
$ git bundle create /tmp/warehouse.bundle --all
//restore your repo from a single file
$ git clone /tmp/warehouse.bundle
"git archive" exports your repository *without* metadata:
//archive your code as a bzipped tarball
$ git archive --format=tar --prefix=linux-4.5/ v4.5 | bzip2 > /tmp/linux-4.5.tar.bz2
//archive your code to a directory
$ mkdir /tmp/linux-4.5
$ git archive v4.5 | tar -xf - -C /tmp/linux-4.5
NOTE: Use "HEAD" instead of the tag to archive current branch.
$ cat .git/COMMIT_TEMPLATE
FIX BUG: PLACEHOLDER(remove this line if this is *NOT* a bugfix)
$ grep template .git/config
template = .git/COMMIT_TEMPLATE
With configurations above, whenever you run "git commit -e", the editor
will have the template file read in.
Git tracks regular files only. To track an empty directory, you need to do
something like:
$ mkdir emptydir
$ echo "!.gitignore" > emptydir/.gitignore
$ git add emptydir
That is, tell git to track a ".gitignore" file, which tells git to ignore
everything but itself.
FYI ".gitignore" is a regular file tracked by git; ".git/info/exclude"
is a git configuration file without being tracked.
//before removal, backup your files
$ mkdir /tmp/backup
$ git ls-files --others --exclude-stardard -z |cpio -pmd0 /tmp/backup
//remove untracked files
$ git clean -d -f
//diff a particular file between 2 branches
$ git diff master staging fs/ext4/inode.c
//diff two branches
$ git diff master staging
or:
$ git diff master..staging
//diff what's in staging since it divorced from master
$ git diff master...staging
Adding the following function to your ~/.bashrc:
parse_git_branch()
{
git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1) /'
}
export PS1="\$(parse_git_branch)$PS1"
If you enter a dir or subdir of a git repo, bash will show:
(staging) [user@host dir]$
FYI $HOME/.gitconfig is global, while “.git/config” is repository wide.
$ cat ~/.gitconfig
[user]
name = Jike Song
email = jike.song@intel.com
[core]
filemode = true
bare = false
pager = less -NFL
editor = vim -c 'set ft=diff' -c 'set spell'
gitproxy = none for intel.com
gitproxy = /usr/bin/socks-gw
quotepath = false
[color]
diff = true
status = true
interactive = true
branch = true
grep = true
[daemon]
receivepack = false
[gc]
auto = true
[alias]
co = checkout
br = branch
st = status
df = diff
desc = describe
changelog = log ORIG_HEAD.. --no-merges
outgoing = log origin/master..HEAD
shrink = gc --aggressive --prune=all
ignored = ls-files --others -i --exclude-standard
[push]
default = current
[sendemail]
smtpserver = smtp.intel.com
smtpport = 25
thread = true
chainreplyto = false
git rebase
git reset
git reflog
git am, git cherry-pick
git send-email
git grep
git ls-files
git merge-base
git submodule
Wikipedia:
https://en.wikipedia.org/wiki/Git_(software)
10 years git interview:
https://www.linux.com/blog/10-years-git-interview-git-creator-linus-torvalds
Google Tech Talk: Linus Torvalds on Git:
https://www.youtube.com/watch?v=4XpnKHJAok8
Pro Git:
https://git-scm.com/book/en/v2
RTFM
man git
{git source}/Documentation
rypress
http://rypress.com/tutorials/git/index