配置及幫助相關(guān)
設(shè)置配置:git config --global user.name "John Doe"
查看配置及出處:git config --show-origin rerere.autoUpdate
查看幫助:git help <verb>
基本命令
將目錄初始化為git目錄:git init
克隆已有的項(xiàng)目:git clone https://github.com/libgit2/libgit2 mylibgit
查看文件狀態(tài):git status -s
移除文件:git rm (-f參數(shù)強(qiáng)制移除被修改的文件,如果文件被修改了官份,默認(rèn)是不會(huì)被移除的)
取消文件跟蹤:git rm --cached
移動(dòng)文件:git mv file_from file_to
查看歷史:git log (-p:顯示差異;-2:最近兩次記錄河咽;--stat:文件狀態(tài))
自定義格式歷史記錄及合并路徑:git log --pretty=format:"%h - %an, %ar : %s" --graph
從標(biāo)記中回退:git reset HEAD <file>
退回到上次提交的版本:git checkout -- <file>
查看遠(yuǎn)端:git remote -v
添加遠(yuǎn)端:git remote add <shortname> <url>
拉取數(shù)據(jù):git fetch/git pull
推送數(shù)據(jù):git push <remote> <branch>
查看本地與遠(yuǎn)端分支對(duì)應(yīng)情況:git remote show origin
重命名/刪除遠(yuǎn)端:git remote rename pb paul / git remote remove paul
查看/查找tag:git tag/git tag -l "v1.8.5*"
創(chuàng)建匿名tag:git tag -a v1.4 -m "my version 1.4"
補(bǔ)打tag:git tag -a v1.2 9fceb02
推送tag:git push origin v1.5/git push origin --tags
刪除本地/遠(yuǎn)端tag:git tag -d <tagname>/git push origin --delete <tagname>
牽出tag:git checkout 2.0.0
基于tag創(chuàng)建分支:git checkout -b version2 v2.0.0
分支
創(chuàng)建分支:git branch testing
切換分支:git checkout testing
創(chuàng)建并切換分支:git checkout -b <newbranchname>
合并分支:git merge hotfix
刪除分支:git branch -d hotfix
查看分支:git branch (-v:顯示最后commit飒房,--merged/--no-merged:過(guò)濾已經(jīng)合并/未合并到當(dāng)前分支的分支狠毯,git branch --no-merged master:是否合并到master的分支)
同步到遠(yuǎn)程分支:git push <remote> <branch> (git push origin serverfix 等效于 git push origin refs/heads/serverfix:refs/heads/serverfix)
創(chuàng)建本地分支并跟蹤對(duì)應(yīng)的遠(yuǎn)程分支:git checkout -b <branch> <remote>/<branch> / git checkout --track origin/serverfix / git checkout <branch>
設(shè)置本地分支的跟蹤遠(yuǎn)程分支:git branch -u origin/serverfix
顯示本地分支與遠(yuǎn)程分支的對(duì)應(yīng)情況:git branch -vv
更新本地git數(shù)據(jù):git fetch --all
更新本地git數(shù)據(jù)并合并當(dāng)前分支:git pull
刪除遠(yuǎn)端分支:git push origin --delete <branch>
變基:git rebase <branch>
取出client分支嚼松,找出處于client(client是基于server開(kāi)出的分支)分支和server分支的共同祖先之后的修改惜颇,然后把她們?cè)趍aster分支上重新放一遍: git rebase --onto master server client
變基遠(yuǎn)端:git pull --rebase
Git服務(wù)器
克隆裸倉(cāng)庫(kù):git clone --bare my_project my_project.git
將裸倉(cāng)庫(kù)放置到服務(wù)器上:scp -r my_project.git user@git.example.com:/srv/git
通過(guò)git將倉(cāng)庫(kù)目錄的組權(quán)限設(shè)置為可寫:git init --bare --shared
SSH Key目錄:cd ~/.ssh
創(chuàng)建sshkey:ssh-keygen -o
打印sshkey公鑰:cat ~/.ssh/id_rsa.pub
創(chuàng)建git用戶和對(duì)應(yīng)的.ssh目錄
$ sudo adduser git
$ su git
$ cd
$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
添加用戶公鑰:cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys
創(chuàng)建并初始化git:
$ cd /srv/git
$ mkdir project.git
$ cd project.git
$ git init --bare
已經(jīng)設(shè)置了git用戶和git倉(cāng)庫(kù)的服務(wù)器,快速添加新項(xiàng)目:
$ cd myproject
$ git init
$ git add .
$ git commit -m 'initial commit'
$ git remote add origin git@gitserver:/srv/git/project.git
$ git push origin master
限制git用戶活動(dòng)在與git相關(guān)范圍內(nèi):
$ cat /etc/shells # see if `git-shell` is already in there. If not...
$ which git-shell # make sure git-shell is installed on your system.
$ sudo -e /etc/shells # and add the path to git-shell from last command
$ sudo chsh git -s $(which git-shell)
分布式Git
生成patch:git format-patch -M origin/master
應(yīng)用patch:git am 0001-limit-log-function.patch
查看不在master上的commit:git log contrib --not master
查看當(dāng)前分支與目標(biāo)分支自從公共基點(diǎn)后的commit:git diff master...contrib
查看共同父commit:git merge-base contrib master
展示修改:git diff
只合并特定節(jié)點(diǎn):git cherry-pick e43a6
準(zhǔn)備發(fā)布:git archive master --prefix='project/' | gzip > git describe master
.tar.gz / git archive master --prefix='project/' --format=zip > git describe master
.zip
查看遠(yuǎn)端所有分支锨亏,包括pull request:git ls-remote https://github.com/schacon/blink
Git工具
查看單個(gè)提交:
$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
$ git show 1c002dd4b536e7479f
$ git show 1c002d
選擇父節(jié)點(diǎn):HEAD^
experiment上有但master上沒(méi)有的提交:git log master..experiment
refA或refB上有但是refC上沒(méi)有的提交: git log refA refB --not refC
顯示master或者experiment中包含但不是兩者共有的提交:git log --left-right master...experiment
交互式暫存:git add -i
暫存工作:git stash / git stash push -m
刪除暫存:git stash drop
應(yīng)用并刪除暫存:git stash pop
查看所有暫存:git stash list
暫存并不重置工作區(qū):git stash --keep-index
同時(shí)暫存未跟蹤的文件:git stash -u
清理工作目錄:git clean -f -d
查找某個(gè)常量何時(shí)引入:git log -S ZLIB_BUF_MAX --oneline
查找zlib.c文件中g(shù)it_deflate_bound in the函數(shù)的每一次變更:git log -L :git_deflate_bound:zlib.c
修改最后一次提交:git commit --amend
修改前三個(gè)父節(jié)點(diǎn)的提交:git rebase -i HEAD~3
僅移動(dòng)HEAD:git reset --soft
移動(dòng)HEAD及索引:git reset --mixed (默認(rèn))
移動(dòng)HEAD并更新目錄:git reset --hard
squash提交
git reset --soft HEAD~2
git commit
回退記錄:git revert -m 1 HEAD
假合并:git merge -s ours mundo
查找bug引入源:git blame -L 69,82 Makefile
查看代碼原來(lái)在哪里:git blame -C -L 141,153 GITPackUpload.m
二分查找:
$ git bisect start
$ git bisect bad
$ git bisect good v1.0
打包分支:git bundle create repo.bundle HEAD master
克隆打包:git clone repo.bundle repo
打包c(diǎn)ommit:git bundle create commits.bundle master ^9a466c5
驗(yàn)證包:git bundle verify ../commits.bundle
查看包分支:git bundle list-heads ../commits.bundle
導(dǎo)入包內(nèi)容:git fetch ../commits.bundle master:other-master
自定義Git
查看git支持的選項(xiàng)列表:man git-config
Git內(nèi)部遠(yuǎn)離
.git目錄下的核心內(nèi)容:HEAD 文件、(尚待創(chuàng)建的)index 文件乾翔,和 objects 目錄反浓、refs 目錄辆雾。objects 目錄存儲(chǔ)所有數(shù)據(jù)內(nèi)容月劈;refs 目錄存儲(chǔ)指向數(shù)據(jù)(分支)的提交對(duì)象的指針猜揪;HEAD 文件指示目前被檢出的分支湿右;index 文件保存暫存區(qū)信息
數(shù)據(jù)對(duì)象
Git的數(shù)據(jù)對(duì)象有四種:blob文件對(duì)象、tree樹(shù)對(duì)象吭狡、commit提交對(duì)象和tag標(biāo)簽對(duì)象
文件對(duì)象
創(chuàng)建新文件并存儲(chǔ)入數(shù)據(jù)內(nèi)容數(shù)據(jù)庫(kù):
$ echo 'version 1' > test.txt
$ git hash-object -w test.txt
接著划煮,向文件里寫入新內(nèi)容,并再次將其存入數(shù)據(jù)庫(kù):
$ echo 'version 2' > test.txt
$ git hash-object -w test.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
可以查看到不同的版本內(nèi)容被記錄下來(lái):
$ find .git/objects -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
現(xiàn)在可以把文件內(nèi)容恢復(fù)到某個(gè)版本:
$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
$ cat test.txt
version 1
$ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt
$ cat test.txt
version 2
樹(shù)對(duì)象
一個(gè)樹(shù)對(duì)象包含了一條或多條樹(shù)對(duì)象記錄(tree entry)俐载,每條記錄含有一個(gè)指向數(shù)據(jù)對(duì)象或者子樹(shù)對(duì)象的 SHA-1 指針挖炬,以及相應(yīng)的模式状婶、類型、文件名信息:
$ git cat-file -p master^{tree}
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README
100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib
$ git cat-file -p 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0
100644 blob 47c6340d6459e05787f644c2447d2595f5d3a54b simplegit.rb
為創(chuàng)建一個(gè)樹(shù)對(duì)象钓猬,首先需要通過(guò)暫存一些文件來(lái)創(chuàng)建一個(gè)暫存區(qū)
git update-index --add --cacheinfo 100644 83baae61804e65cc73a7201a7252750c76066a30 test.txt
將暫存取寫入樹(shù)對(duì)象
$ git write-tree
d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
100644 blob 83baae61804e65cc73a7201a7252750c76066a30 test.txt
提交對(duì)象
提交對(duì)象包含了一個(gè)頂層樹(shù)對(duì)象敞曹,代表當(dāng)前項(xiàng)目快照:
$ echo 'first commit' | git commit-tree d8329f
fdf4fc3344e67ab068f836878b6c4951e3b15f3d
$ git cat-file -p fdf4fc3
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author Scott Chacon <schacon@gmail.com> 1243040974 -0700
committer Scott Chacon <schacon@gmail.com> 1243040974 -0700
first commit
創(chuàng)建另外兩個(gè)提交對(duì)象异雁,格子飲用上一個(gè)提交:
$ echo 'second commit' | git commit-tree 0155eb -p fdf4fc3
cac0cab538b970a37ea1e769cbbde608743bc96d
$ echo 'third commit' | git commit-tree 3c4e9c -p cac0cab
1a410efbd13591db07496601ebc7a059dd55cfe9
這就是每次我們運(yùn)行 git add 和 git commit 命令時(shí)僧须, Git 所做的實(shí)質(zhì)工作——將被改寫的文件保存為數(shù)據(jù)對(duì)象担平,更新暫存區(qū)暂论,記錄樹(shù)對(duì)象取胎,最后創(chuàng)建一個(gè)指明了頂層樹(shù)對(duì)象和父提交的提交對(duì)象闻蛀。 這三種主要的 Git 對(duì)象——數(shù)據(jù)對(duì)象觉痛、樹(shù)對(duì)象薪棒、提交對(duì)象——最初均以單獨(dú)文件的形式保存在 .git/objects 目錄下
標(biāo)簽對(duì)象
標(biāo)簽對(duì)象通常指向一個(gè)提交對(duì)象俐芯,而不是一個(gè)樹(shù)對(duì)象吧史。 它像是一個(gè)永不移動(dòng)的分支引用——永遠(yuǎn)指向同一個(gè)提交對(duì)象扣蜻,只不過(guò)給這個(gè)提交對(duì)象加上一個(gè)更友好的名字罷了莽使》技。可以像這樣創(chuàng)建一個(gè)輕量標(biāo)簽:
$ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d
若要?jiǎng)?chuàng)建一個(gè)附注標(biāo)簽亿笤,Git 會(huì)創(chuàng)建一個(gè)標(biāo)簽對(duì)象,并記錄一個(gè)引用來(lái)指向該標(biāo)簽對(duì)象汪榔,而不是直接指向提交對(duì)象。 可以通過(guò)創(chuàng)建一個(gè)附注標(biāo)簽來(lái)驗(yàn)證這個(gè)過(guò)程(-a 選項(xiàng)指定了要?jiǎng)?chuàng)建的是一個(gè)附注標(biāo)簽):
$ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'test tag'
$ cat .git/refs/tags/v1.1
9585191f37f7b0fb9444f35a9bf50de191beadc2
$ git cat-file -p 9585191f37f7b0fb9444f35a9bf50de191beadc2
object 1a410efbd13591db07496601ebc7a059dd55cfe9
type commit
tag v1.1
tagger Scott Chacon <schacon@gmail.com> Sat May 23 16:48:58 2009 -0700
test tag
refs引用
引用是一個(gè)文件來(lái)保存 SHA-1 值燃领,并給文件起一個(gè)簡(jiǎn)單的名字猛蔽,然后用這個(gè)名字指針來(lái)替代原始的 SHA-1 值区岗。
git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9
這基本就是Git分支的本質(zhì)凉泄,一個(gè)指向某一系列提交之首的指針或引用:
git update-ref refs/heads/test cac0ca
HEAD
HEAD 文件是一個(gè)符號(hào)引用(symbolic reference)胀糜,指向目前所在的分支教藻。 所謂符號(hào)引用括堤,意味著它并不像普通引用那樣包含一個(gè) SHA-1 值——它是一個(gè)指向其他引用的指針讥电。當(dāng)我們執(zhí)行 git commit 時(shí)恩敌,該命令會(huì)創(chuàng)建一個(gè)提交對(duì)象纠炮,并用 HEAD 文件中那個(gè)引用所指向的 SHA-1 值設(shè)置其父提交字段
$ cat .git/HEAD
ref: refs/heads/master
$ git symbolic-ref HEAD
refs/heads/master
$ git symbolic-ref HEAD refs/heads/test
$ cat .git/HEAD
ref: refs/heads/test
Git包文件
Git 最初向磁盤中存儲(chǔ)對(duì)象時(shí)所使用的格式被稱為“松散(loose)”對(duì)象格式。 但是灯蝴,Git 會(huì)時(shí)不時(shí)地將多個(gè)這些對(duì)象打包成一個(gè)稱為“包文件(packfile)”的二進(jìn)制文件恢口,以節(jié)省空間和提高效率。 當(dāng)版本庫(kù)中有太多的松散對(duì)象穷躁,或者你手動(dòng)執(zhí)行 git gc 命令耕肩,或者你向遠(yuǎn)程服務(wù)器執(zhí)行推送時(shí),Git 都會(huì)這樣做折砸。Git 打包對(duì)象時(shí)看疗,會(huì)查找命名及大小相近的文件,并只保存文件不同版本之間的差異內(nèi)容睦授。 你可以查看包文件,觀察它是如何節(jié)省空間的摔寨。 git verify-pack 這個(gè)底層命令可以讓你查看已打包的內(nèi)容删顶。
引用規(guī)格
引用規(guī)格的格式由一個(gè)可選的 + 號(hào)和緊隨其后的 <src>:<dst> 組成季惩,其中 <src> 是一個(gè)模式(pattern),代表遠(yuǎn)程版本庫(kù)中的引用;<dst> 是那些遠(yuǎn)程引用在本地所對(duì)應(yīng)的位置嫡意。 + 號(hào)告訴 Git 即使在不能快進(jìn)的情況下也要(強(qiáng)制)更新引用促煮∽迹可在.git/config文件中配置:
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/*:refs/remotes/origin/*
push = refs/heads/master:refs/heads/qa/master
數(shù)據(jù)恢復(fù)
reset后找回丟失的commit痹仙,并基于丟失的提交創(chuàng)建分支
git reflog
git branch recover-branch ab1afef
找回丟失的分支
git fsck --full
git庫(kù)刪除大的文件記錄
//查找最大的文件
git verify-pack -v .git/objects/pack/pack-29…69.idx \
| sort -k 3 -n \
| tail -3
//顯示blob對(duì)應(yīng)的文件
$ git rev-list --objects --all | grep 82c99a3
82c99a3e86bb1267b236a4b6eff7868d97489af1 git.tgz
//查找包含這個(gè)blob的commit
git log --oneline --branches -- git.tgz
//重寫commit恩溅,從某個(gè)提交之后的所有commit中刪除對(duì)應(yīng)的blob
git filter-branch --index-filter \
'git rm --ignore-unmatch --cached git.tgz' -- --all
rm -Rf .git/refs/original
rm -Rf .git/logs/
git gc
//移除不可引用的blob
git prune