Git常用命令

配置及幫助相關(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)是不會被移除的)
取消文件跟蹤: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)端分支對應(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

分支

git commit記錄與blob.png

創(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:過濾已經(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)建本地分支并跟蹤對應(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)程分支的對應(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開出的分支)分支和server分支的共同祖先之后的修改,然后把她們在master分支上重新放一遍: git rebase --onto master server client
變基遠(yuǎn)端:git pull --rebase

Git服務(wù)器

克隆裸倉庫:git clone --bare my_project my_project.git
將裸倉庫放置到服務(wù)器上:scp -r my_project.git user@git.example.com:/srv/git
通過git將倉庫目錄的組權(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用戶和對應(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倉庫的服務(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上沒有的提交:git log master..experiment
refA或refB上有但是refC上沒有的提交:git log refA refB ^refC / 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
查看代碼原來在哪里: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 目錄存儲所有數(shù)據(jù)內(nèi)容;refs 目錄存儲指向數(shù)據(jù)(分支)的提交對象的指針;HEAD 文件指示目前被檢出的分支;index 文件保存暫存區(qū)信息

數(shù)據(jù)對象

Git的數(shù)據(jù)對象有四種:blob文件對象、tree樹對象、commit提交對象和tag標(biāo)簽對象

文件對象

創(chuàng)建新文件并存儲入數(shù)據(jù)內(nèi)容數(shù)據(jù)庫:

$ echo 'version 1' > test.txt
$ git hash-object -w test.txt

接著,向文件里寫入新內(nèi)容,并再次將其存入數(shù)據(jù)庫:

$ echo 'version 2' > test.txt
$ git hash-object -w test.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a

可以查看到不同的版本內(nè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

樹對象

一個(gè)樹對象包含了一條或多條樹對象記錄(tree entry),每條記錄含有一個(gè)指向數(shù)據(jù)對象或者子樹對象的 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è)樹對象,首先需要通過暫存一些文件來創(chuàng)建一個(gè)暫存區(qū)

git update-index --add --cacheinfo 100644 83baae61804e65cc73a7201a7252750c76066a30 test.txt

將暫存取寫入樹對象

$ git write-tree
d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
100644 blob 83baae61804e65cc73a7201a7252750c76066a30      test.txt

提交對象

提交對象包含了一個(gè)頂層樹對象,代表當(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è)提交對象,格子飲用上一個(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ù)對象,更新暫存區(qū),記錄樹對象,最后創(chuàng)建一個(gè)指明了頂層樹對象和父提交的提交對象。 這三種主要的 Git 對象——數(shù)據(jù)對象、樹對象、提交對象——最初均以單獨(dú)文件的形式保存在 .git/objects 目錄下

標(biāo)簽對象

標(biāo)簽對象通常指向一個(gè)提交對象,而不是一個(gè)樹對象。 它像是一個(gè)永不移動(dòng)的分支引用——永遠(yuǎn)指向同一個(gè)提交對象,只不過給這個(gè)提交對象加上一個(gè)更友好的名字罷了??梢韵襁@樣創(chuàng)建一個(gè)輕量標(biāo)簽:

$ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d

若要?jiǎng)?chuàng)建一個(gè)附注標(biāo)簽,Git 會創(chuàng)建一個(gè)標(biāo)簽對象,并記錄一個(gè)引用來指向該標(biāo)簽對象,而不是直接指向提交對象。 可以通過創(chuàng)建一個(gè)附注標(biāo)簽來驗(yàn)證這個(gè)過程(-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è)文件來保存 SHA-1 值,并給文件起一個(gè)簡單的名字,然后用這個(gè)名字指針來替代原始的 SHA-1 值。

git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9

這基本就是Git分支的本質(zhì),一個(gè)指向某一系列提交之首的指針或引用:

git update-ref refs/heads/test cac0ca

HEAD

HEAD 文件是一個(gè)符號引用(symbolic reference),指向目前所在的分支。 所謂符號引用,意味著它并不像普通引用那樣包含一個(gè) SHA-1 值——它是一個(gè)指向其他引用的指針。當(dāng)我們執(zhí)行 git commit 時(shí),該命令會創(chuàng)建一個(gè)提交對象,并用 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 最初向磁盤中存儲對象時(shí)所使用的格式被稱為“松散(loose)”對象格式。 但是,Git 會時(shí)不時(shí)地將多個(gè)這些對象打包成一個(gè)稱為“包文件(packfile)”的二進(jìn)制文件,以節(jié)省空間和提高效率。 當(dāng)版本庫中有太多的松散對象,或者你手動(dòng)執(zhí)行 git gc 命令,或者你向遠(yuǎn)程服務(wù)器執(zhí)行推送時(shí),Git 都會這樣做。Git 打包對象時(shí),會查找命名及大小相近的文件,并只保存文件不同版本之間的差異內(nèi)容。 你可以查看包文件,觀察它是如何節(jié)省空間的。 git verify-pack 這個(gè)底層命令可以讓你查看已打包的內(nèi)容。

引用規(guī)格

引用規(guī)格的格式由一個(gè)可選的 + 號和緊隨其后的 <src>:<dst> 組成,其中 <src> 是一個(gè)模式(pattern),代表遠(yuǎn)程版本庫中的引用;<dst> 是那些遠(yuǎn)程引用在本地所對應(yīng)的位置。 + 號告訴 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庫刪除大的文件記錄

//查找最大的文件
git verify-pack -v .git/objects/pack/pack-29…69.idx \
  | sort -k 3 -n \
  | tail -3
//顯示blob對應(yīng)的文件
$ git rev-list --objects --all | grep 82c99a3
82c99a3e86bb1267b236a4b6eff7868d97489af1 git.tgz
//查找包含這個(gè)blob的commit
git log --oneline --branches -- git.tgz
//重寫commit,從某個(gè)提交之后的所有commit中刪除對應(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容