【工具】Git 基礎
Git 基礎
Git 簡介
Git 是一個開源的分散式版本控制系統,用於高效地管理任何或小或大的專案。
在 Linux 發展的時候,程式碼的管理是手工合併的,效率很低,所以 Linus 用 C 語言開發了一套分散式的版本控制系統 Git,之後 Linux 開原始碼的管理就放在了 Git 上管理了。後來 GitHub 的上線也讓 Git 風靡至今。
安裝和配置 Git
- 安裝 Git:
sudo apt install git
- 配置 Git:設定 name 和 email,因為 Git 在每次 commit 時都會記錄這些資訊。
git config --global user.name "name"
git config --global user.email "[email protected]"
如果用了
--global
選項,那麼配置檔案儲存在~/.gitconfig
中,否則儲存在當前專案的.git/config
檔案中,後者會覆蓋前者的配置。
工作區、暫存區和版本庫
- 工作區:電腦中的一個目錄。
- 版本庫:工作區中有一個隱藏目錄
.git
,這是 Git 的版本庫。 - 暫存區:暫存區是
.git/index
檔案。
建立倉庫
git init
在一個目錄下,使用git init
命令來初始化一個倉庫,此後該目錄才成為一個工作區。
在執行完成git init
命令後,工作區會生成一個.git
git clone
如果在遠端倉庫中已經有現有的專案,可以使用git clone
從遠端倉庫中拷貝專案,該命令會自動建立專案目錄。例如:git clone git://github.com/schacon/grit.git
git clone
可以使用不同的協議,包括ssh, git, https
等,其中最常用的是https
。各種寫法如下:
# SSH 協議 git clone [email protected]:zghong/test.git # GIT 協議 git clone git://github.com/zghong/test.git # HTTPS 協議 git clone https://github.com/zghong/test.git # 指定分支 git clone -b develop https://github.com/zghong/test.git # 淺拷貝 git clone --depth 1 https://github.com/zghong/test.git
一般倉庫不大時,我們可以直接使用git clone
倉庫,但如果在倉庫歷史的某次 commit 不小心提交了 1G 的檔案,雖然後面把這個檔案刪除了,但是版本庫(.git資料夾
)中仍然儲存著這個檔案,所以如果我們仍然使用git clone
這個倉庫,會把所有版本記錄 clone 下來,這樣整個倉庫會非常大。如果僅僅是使用倉庫,而不是管理倉庫,只要把最近的一次 commit 給 clone 下來就好了,實現這個功能就需要用到git clone --depth=1
命令。
基本操作
git status 和 git log
git status
:檢視在你上次提交之後是否有修改。git log
:檢視提交日誌。git reflog
:檢視歷史操作和對應的commit id
git add
git add
:可將增刪改的檔案新增到暫存區。
git add READEME hello.c
git add *.c
git add *
git commit
git commit
將暫存區內容提交到版本庫中,並可以使用-m
選項以在命令列中提供提交註釋。
每一次git commit
就相當於建立一個還原點,並生成一個對應的commit id
,commit id
是一個 SHA1 計算出來的一個非常大的數字,用十六進位制表示。
git commit -m 不帶空格註釋
git commit -m "帶空格 的註釋"
git diff
git diff
:顯示檔案修改的區別。
- 對比尚未暫存的改動:
git diff
- 對比已暫存的改動:
git diff --cached
- 對比已暫存的與未暫存的所有改動:
git diff HEAD
- 對比工作區和暫存區的不同:
git diff HEAD -- 檔名
- 對比兩個版本的不同:
git diff HEAD HEAD^ -- 檔名
git rm
當使用rm test.txt
刪除了倉庫中的檔案時,接下來有兩種情況:
- 確實要刪除:
git rm test.txt
或者git add test.txt
,並提交。 - 誤刪除:
git checkout -- test.txt
即可恢復檔案。
撤銷修改
- 當修改沒有新增到暫存區時,丟棄工作區的改動:
git checkout -- 檔名
- 當修改已經新增到暫存區時,取消暫存:
- 新檔案:
git rm --cached 檔名
- 修改檔案:
git reset HEAD 檔名
- 新檔案:
- 當修改已經新增到暫存區並且已經建立了一個版本時:
git reset --soft|--mixed|--hard <commit_id>
git reset --soft HEAD^
:撤銷最近一次 commit,不撤銷 git add。git reset --mixed HEAD^
:預設操作,撤銷最近一次 commit,撤銷 git add。git reset --hard HEAD^
:撤銷最近一次的 commit,撤銷 git add,並且放棄修改。
分支管理
分支可以類似於兩個平行的宇宙。主要用於去開闢一個新的分支去實現一個新的功能,這個分支並不會對其他分支產生任何影響。當功能開發完善之後,還可以將新分支的內容一次性合併到主分支 master 上。這樣既安全有不影響其他人的正常工作。
建立和合並分支
在建立倉庫時會預設建立一個主分支master
,指標是HEAD
。當建立一個分支dev
時,將HEAD
指標指向dev
分支。可以指定當前工作分支在哪一個分支上,之後的修改提交就會記錄在該分支下。
- 檢視分支:
git branch
- 建立分支:
git branch 分支名
- 建立並切換分支:
git checkout -b 分支名
- 切換分支:
git checkout 分支名
- 將某個分支合併到當前所在分支:
git merge 分支名
- 刪除分支:
git branch -d 分支名
合併衝突
當兩個分支沒有同時有兩個相同的修改時,合併時預設採用Fast-forward
,即快速合併。但是如果兩個分支修改的內容有衝突時會發生合併衝突,這時就需要手動解決衝突。
- 禁止快速合併:
git merge --no-ff -m '版本資訊' 分支名
標籤管理
如之前所說,每一次 commit 就是建立一個版本,但是由於 commit 號是使用 SHA-1 生成的,不容易記住且沒有意義,因此標籤應運而生。
tag 就是一個讓人容易記住的有意義的名字,它跟某個 commit 綁在一起,其實它就是指向某個 commit 的指標。
當釋出一個版本時,我們通常先在版本庫中打一個 tag,這樣就唯一確定了打標籤時刻的版本。將來無論什麼時候,取某個標籤的版本,就是把那個打標籤的時刻的歷史版本取出來。
建立標籤
git tag tag名 [commit id] -m "註釋"
:建立一個標籤,預設標籤是打在最新提交的 commit 上的。例如git tag v1.0 -m "Release Edition v1.0"
git tag
:檢視所有標籤。git show tag名
:檢視標籤資訊。
操作標籤
因為建立的標籤都只儲存在本地,不會自動推送到遠端。如果需要同步遠端倉庫,需要使用單獨的命令對標籤進行同步。
- 刪除本地標籤:
git tag -d tag名
- 刪除遠端標籤名:
git tag -d tag名
:先刪除本地標籤。git push origin :refs/tags/tag名
:刪除遠端標籤名。
- 推送標籤:
git push orgin tag名
- 一次性推送所有未推送到遠端的標籤名:
git push origin --tags
GitHub 的使用
新增 ssh 公鑰
如果某臺電腦需要與 GitHub 倉庫進行互動就需要將這臺電腦的 ssh 公鑰新增到 GitHub 賬號上。
- 在本機生成 ssh 祕鑰:
ssh-keygen -t rsa -C "[email protected]"
。 - 將使用者目錄下的
.ssh
資料夾下的id_rsa.pub
公鑰新增在 GitHub 設定中。 - 驗證是否新增成功:
ssh -T [email protected]
克隆和上傳專案
克隆專案
從遠端倉庫克隆一個已存在的專案只需要一條命令即可。
- 不指定分支:
git clone [email protected]:zghong/haha.git
- 指定分支:
git clone -b dev [email protected]:zghong/haha.git
上傳專案
已經在本地建立了一個 Git 倉庫後,想把本地專案上傳到 GitHub 上,並且讓這兩個倉庫進行遠端同步,這樣,GitHub 上的倉庫既可以作為備份,又可以讓其他人通過該倉庫來協作。
- 在 Github 上建立一個空倉庫 hehe。
git remote add origin [email protected]:zghong/hehe.git
,將遠端庫與本地建立關聯。git push -u origin master
,把本地庫的所有內容推送到遠端庫上。
由於遠端庫是空的,我們第一次推送 master 分支時,加上了
-u
引數,Git 不但會把本地的 master 分支內容推送的遠端新的 master 分支,還會把本地的 master 分支和遠端的 master 分支關聯起來,在以後的推送或者拉取時就可以簡化命令。
推送和拉取程式碼
- 推送程式碼:
git push origin 分支名
- 拉取程式碼:
git pull origin 分支名