[工具] Git-基礎
Git 基礎
Git 簡介
Git 是一個開源的分散式版本控制系統,用於高效地管理任何或小或大的專案。
在 Linux 發展的時候,程式碼的管理是手工合併的,效率很低,所以 Linus 開發了一套分散式的版本控制系統 Git,之後 Linux 開原始碼的管理就放在了 Git 上管理,同時 GitHub 的上線也讓 Git 風靡至今。
安裝和配置 Git
- 安裝 Git:
sudo apt install git
- 配置 Git:設定 name 和 email,因為在每次 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/zghong/test.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
.git資料夾
)中仍然儲存著這個檔案,所以如果我們仍然使用git clone
,會把所有版本記錄 clone 下來,這樣整個倉庫會非常大。如果僅僅是使用倉庫,而不是管理倉庫,只要把最近的一次 commit 給 clone 下來即可,實現這個功能需要用到git clone --depth=1
命令,也稱「淺拷貝」。
# 指定分支
git clone -b develop https://github.com/zghong/test.git
# 淺拷貝
git clone --depth 1 https://github.com/zghong/test.git
基本操作
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 [-- filename1 filename2]
- 對比已暫存的改動:
git diff --cached [-- filename1 filename2]
- 對比已暫存的與未暫存的所有改動:
git diff HEAD [-- filename1 filename2]
- 對比兩個版本的不同:
git diff HEAD HEAD^ [-- filename1 filename2]
git rm
當使用rm test.txt
刪除了倉庫中的檔案時,接下來有兩種情況:
- 確實要刪除:
git rm test.txt
或者git add test.txt
,並提交。 - 誤刪除:
git checkout -- test.txt
即可恢復檔案。
撤銷修改
- 當修改沒有新增到暫存區時,丟棄工作區的改動:
git checkout -- filename
- 當修改已經新增到暫存區時,取消暫存:
- 新檔案:
git rm --cached filename
- 修改的檔案:
git reset HEAD filename
- 新檔案:
- 當修改已經新增到暫存區並且已經建立了一個版本時:
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,指標是HEAD
。當建立一個分支 dev 時,將HEAD
指標指向 dev 分支。可以指定當前工作分支在哪一個分支上,之後的修改提交就會記錄在該分支下。
- 檢視分支:
git branch
- 建立分支:
git branch 分支名
- 建立並切換分支:
git checkout -b 分支名
- 切換分支:
git checkout 分支名
- 將某個分支合併到當前所在分支:
git merge 分支名
- 刪除分支:
git branch -d 分支名
合併衝突
合併 dev 分支到 master 分支,會出現以下三種情況:
- master 分支沒有提交,僅僅 dev 分支有提交:合併時預設採用
Fast-forward
,即快速合併。合併之後相當於直接在 master 分支操作一樣,在使用git log --graph --pretty=oneline
時看到的版本圖沒有分支提交部分。所以有時為了在版本圖中體現出這種分支關係,我們會在合併時禁用快速合併:git merge --no-ff dev -m '禁用 fast-forward 合併'
,這時會在 master 分支進行一次新的提交。 - master 分支和 dev 分支都有提交,但是沒有衝突:合併時會提示建立一次新提交。
- master 分支和 dev 分支都有提交,並且提交的修改是同一個檔案:發生衝突。
當合併發生了衝突時,Git 會用<<<<, ====, >>>>
等符號在衝突檔案中標記出不同分支修改的內容。這時我們需要先手動解決衝突(刪除衝突檔案中的標記符號,並修改衝突部分),然後再提交一次修改,之後才能合併。
標籤管理
如之前所說,每一次 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 上建立一個空倉庫 test。
git remote add origin [email protected]:zghong/test.git
,將遠端庫與本地建立關聯。git push -u origin master
,把本地庫的所有內容推送到遠端庫上。
由於遠端庫是空的,我們第一次推送 master 分支時,加上了
-u
引數,Git 不但會把本地的 master 分支內容推送的遠端新的 master 分支,還會把本地的 master 分支和遠端的 master 分支關聯起來,在以後的推送或者拉取時就可以簡化命令。
推送和拉取程式碼
- 推送程式碼:
git push origin 分支名
- 拉取程式碼:
git pull origin 分支名