概述
Git是一個用來做代碼管理和版本控制的工具。
參考教程
《Git權威指南》,機械工業出版社,蔣鑫。
如有理解錯誤,歡迎指正。
總覽
版本控制工具的發展
1.diff和patch。
2.CVS。
3.SVN。
4.Git。
Git初始化
git配置文件位置。
? - 全局配置:/etc/gitconfig
? - 個人配置:~/.gitconfig
? - 具體Git庫配置:/path/to/repo/.git/config
使用git config配置用戶名和郵箱,--global表示當前用戶。
git config --global user.name "Ruochen Xu"
git config --global user.email "ruochen.xu@aorise.com"
使用git config配置操作別名,可以讓指令變短,--system表示所有用戶。
git config --system alias.st status
注意:git config后的配置項都以a.b的形式表示。使用--unset刪除配置。
使用git init創建空的本地git庫,創建完成后,在庫目錄下有一個.git文件夾,里面存儲了與本git庫相關的所有信息。
cd /path/to/my/workspace
git init demo
生成一個新文件,并使用git add加入暫存區,然后使用git commit作一次的提交。
提交可以看做是一個確認的代碼改動。
cd demo
echo "Hello." > readme.md
git add readme.md
git commit -m "Initialize.”
Git對象
Git中每個文件、每次提交、每個目錄樹等信息,都是以git對象的形式存儲在庫的.git/objects目錄下的。每個git對象都有一個40位的SHA1哈希值,存儲時前兩位作為目錄名,后38位作為文件名。
git cat-file -t <hash> # 查看git對象類型
git cat-file -p <hash> # 查看git對象內容
Git分支
Git進行第一次提交后,會自動生成第一個分支,也是默認分支,名稱為master。
每次git commit提交都可以看做是一個點,相鄰的提交之間有邊相連,git每個提交都是增量的。每個提交都對應有一個文件目錄樹,代表的是從第一次提交開始到該提交結束,庫中的文件。
每個分支就是一個指向某個提交的指針,代表著從第一次提交開始到該提交結束所有的文件變化歷程。每個分支應當有一個獨有的名字,HEAD表示當前正在操作的提交。
新的提交只能在某個分支上進行,即HEAD指針停留在某個分支指針上,而不能在任意提交上進行。
新分支可以從某個提交處產生,舊分支也可以與別的分支合并然后刪除。所以所有的提交構成一張圖。
Git的分支信息都存儲在庫的.git/refs/heads目錄下,庫的.git/HEAD文件存儲HEAD指針的信息,庫的.git/logs/refs/heads目錄下記錄了分支的變化歷史。
Git提交的相對訪問
^,父提交,^2,第二個父提交,例如HEAD^2。
~n,第n個祖先提交,例如HEAD~5。
^{tree},提交所對應的目錄樹,例如HEAD^{tree}。
:path/to/file,提交所對應的目錄樹中的文件,例如HEAD:path/to/file,不帶分支名時指的是暫存區中的文件。
Git分支操作
分支移動。
git commit # 進行一次提交并將當前分支移動到新的提交
git reset <commit> # 將當前分支移動到指定提交
分支查看。
git branch -a
HEAD指針切換。
git checkout <commit>
從當前位置創建新分支。
git checkout -b <branch>
分支合并。
git merge <commit>
分支刪除。
git branch -d <branch>
Git庫類型
Git庫主要分為三種類型。
1.bare,可讀寫的主庫,一般放在遠端服務器上,并設置成不能撤銷寫入的模式。不能在bare庫本地直接對bare庫進行操作。
2.mirror,可讀不可寫的bare庫鏡像,一般放在遠端服務器上,也可以放在開發機上。可以在mirror庫本地操作其與bare庫進行同步。
3.local,可以任意操作的本地庫,放在開發機上。可以與遠端的bare、mirror庫進行交互操作。
Git庫的常規操作流程
1.使用git clone克隆遠端bare庫或者mirror庫到本地,此時遠端bare庫默認使用origin這個名稱。也可以使用git remote add將本地已初始化的庫關聯到遠端bare庫或者mirror庫。
git clone git@github.com:hnxuruochen/test.git
git remote add origin git@github.com:hnxuruochen/test.git
注意:每個local庫都可以有任意多個遠端關聯庫,用不同的名稱區分,origin是默認名稱。
2.使用git pull將遠端bare或者mirror庫的指定分支的最新改動拉到本地當前分支。如果分支之間有沖突則需要進行沖突解決和分支合并。
git pull = git fetch + git merge
git pull origin <branch>
3.使用git push將本地庫的當前分支的最新改動推到遠端bare庫的指定分支。如果分支之間有沖突則需要先通過git pull解決沖突并合并分之后,才能繼續push。
git push origin <branch>
團隊一般通過一個bare庫,每人一個local庫的方式進行合作開發。
Git文件區
Git庫本地分為三個文件區。
1.工作區。存放本地文件的文件系統,對文件的改動都是在工作區完成的。
2.暫存區。用于記錄和追蹤文件狀態的臨時區,庫的.git/index記錄的就是暫存區的目錄樹。
3.版本庫。存放確定文件改動的庫。所有的提交、分支都是在版本庫中的,bare、mirror庫與local庫的交互實際上是版本庫的交互。
提交文件只能從工作區到暫存區,或者暫存區到版本庫。還原文件只能從版本庫到暫存區,或者暫存區到工作區。不能跨區操作。
文件區之間的操作
文件狀態。
git status
文件比較。
git diff # 比較工作區與暫存區
git diff HEAD # 比較工作區與版本庫中的當前提交
git diff --cached?HEAD # 比較暫存區與版本庫中的當前提交
文件提交。
git add?<file> # 從工作區到暫存區
git commit # 從暫存區到版本庫的新提交
文件還原。
git checkout -- <file> # 從暫存區到工作區
git reset HEAD # 從版本庫中的當前提交到暫存區
git checkout HEAD <file> # 從版本庫中的當前提交到暫存區再到工作區
文件刪除。
git rm <file> # ?刪除工作區和暫存區中的文件
git rm --cached <file> # 只刪除暫存區的文件
git clean # 刪除工作區中未加入版本庫的文件
Git存放處
Git還有一個特殊的文件區叫做stash,是用來臨時存放當前工作區和暫存區的改動的。
每次存放相當于是作了一次不被實際應用的提交,然后記錄在庫的.git/refs/stash中,存放的變化存放在庫的.git/logs/refs/stash中。
存儲并撤銷當前工作區和暫存區的改動。
git stash
恢復工作區和暫存區的改動。
git stash pop
查看所有存放的改動。
git stash list
Git里程碑
Git里程碑是人為對提交進行的命名。里程碑相關信息存儲在庫的,git/refs/tags目錄下。
里程碑分類
1.輕量級里程碑,創建時使用-l參數。該里程碑本質上是一個提交,但是沒有創建者信息。
2.帶說明的里程碑,創建時使用-a或-m參數。該里程碑式一個tag對象。
3.帶簽名的里程碑,創建時使用參數-s或者-u。該里程碑也是一個tag對象,還添加了GnuPG簽名。
里程碑操作
顯示里程碑。
git tag
創建里程碑。
git tag <name>
刪除里程碑。
git tag -d <name> # 刪除本地
git push <remote> :<name> # 刪除遠程
推送里程碑。
git push <remote> <name>
Git子模塊
Git庫可以將其他git庫作為子模塊引入。
創建子模塊。
git submodule add <repo_path> <submodule_path>
初始化子模塊。
git submodule init
更新子模塊。
git submodule update
查看子模塊。
git submodule status
其他
文件忽略
可以通過編輯.gitignore文件來讓git忽略一些僅在工作區中的文件,.gitignore文件可以放在任意目錄下,對當前目錄和子目錄生效。
一些復雜的分支操作
git cherry-pick,將指定提交的增量改動應用到當前提交上。
git rebase,將指定的一段連續的增量提交應用到指定提交上。
git revert,使用一個新提交的方式撤銷上一個提交的內容。
文件追溯
git blame指令可以追溯一個文件的改動歷史信息。