Git 版本控制完全指南:從入門到精通
作為當今最流行的分布式版本控制系統,Git 已經成為開發者必備的技能之一。無論你是獨立開發者還是團隊協作,Git 都能幫助你高效管理代碼版本。本文將帶你從零開始,逐步掌握 Git 的核心概念和常用操作。
Git 初始化與配置
git init
這個簡單的命令會在當前目錄創建一個新的 Git 倉庫。Git 倉庫是 Git 用來跟蹤和管理項目變更的核心機制。執行后,你會看到一個隱藏的 .git 文件夾,它包含了 Git 所需的所有倉庫數據。
git config user.name "sin"
git config user.email "123456@qq.com"
這些配置命令非常重要,因為它們設置了提交代碼時的作者信息。Git 會將這些信息附加到你的每一次提交上,這樣其他人就能知道是誰做了哪些修改。
查看配置項:
git config -l
這個命令會列出所有 Git 配置,包括用戶信息、別名設置等。當需要檢查或調試配置問題時非常有用。
刪除配置
git config -unset user.email
如果你需要刪除某個特定的配置項,可以使用這個命令。注意,如果該配置是在全局設置的,你需要使用相同的范圍來刪除它。
一臺服務器可以創建多個本地倉庫,加了global相當于配置在全局都生效。
git config --global user,name "sin"
全局配置(--global
)會將設置應用于當前用戶的所有倉庫,而本地配置(不加--global
)只影響當前倉庫。這在多項目開發中特別有用。
是用global創建的想要重置需要同樣是用global關鍵字。
我們可以進入.get文件:
[sin@VM-4-8-centos gitcode]$ cd .git
[sin@VM-4-8-centos .git]$ tree ./
./
|-- branches
|-- config
|-- description
|-- HEAD
|-- hooks
| |-- applypatch-msg.sample
| |-- commit-msg.sample
| |-- post-update.sample
| |-- pre-applypatch.sample
| |-- pre-commit.sample
| |-- prepare-commit-msg.sample
| |-- pre-push.sample
| |-- pre-rebase.sample
| -- update.sample
|-- info
| -- exclude
|-- objects
| |-- info
| -- pack
-- refs|-- heads-- tags
.git 目錄是 Git 倉庫的核心,包含了所有版本控制所需的數據。其中:
objects
目錄存儲所有數據內容refs
目錄存儲指向分支和標簽的指針HEAD
文件指向當前所在的分支config
文件包含倉庫特定的配置選項
不能再.git文件中手動修改任何內容。手動修改可能會導致倉庫損壞,應該始終使用 Git 命令來操作。
Git 基本工作流程
這張圖清晰地展示了 Git 的三個主要區域:工作區、暫存區(Stage/Index)和版本庫(Repository)。理解這三個區域的關系對掌握 Git 至關重要。
git add file.txt
git add
命令將工作區的修改添加到暫存區。暫存區就像一個準備區,讓你可以精心挑選哪些修改要包含在下一次提交中。
git commit file.txt -m"本次提交的細節"
git commit
命令將暫存區的修改永久保存到版本庫中。提交信息(-m
參數)應該清晰描述這次提交的目的,這對日后回溯歷史非常有幫助。
git log
git log
顯示項目的提交歷史,包括每次提交的作者、日期和提交信息。這是了解項目演變過程的主要方式。
Git 對象模型
[root@VM-4-8-centos gitstudy]# tree .git
.git
|-- branches
|-- COMMIT\_EDITMSG
|-- config
|-- description
|-- HEAD
|-- hooks
| |-- applypatch-msg.sample
| |-- commit-msg.sample
| |-- post-update.sample
| |-- pre-applypatch.sample
| |-- pre-commit.sample
| |-- prepare-commit-msg.sample
| |-- pre-push.sample
| |-- pre-rebase.sample
| -- update.sample
|-- index
|-- info
| -- exclude
|-- logs
| |-- HEAD
| -- refs
| -- heads
| -- master
|-- objects
| |-- 2f
| | -- 96a52bce7a059aab3577e7e9b8499df7aa46dc
| |-- 9c
| | -- 7b41e1c03f5499d21419108d6ef57d0bec1da4
| |-- ec
| | -- 8c05d08dbd2166e7550d64239cd997a35e396c
| |-- info
| -- pack
-- refs|-- heads| -- master-- tags
Git 的核心是一個內容尋址文件系統,這意味著它存儲的是文件內容的哈希值而非文件名。每次提交都會創建一個新的對象存儲在 objects 目錄中。
[root@VM-4-8-centos gitstudy]# cat .git/refs/heads/master
ec8c05d08dbd2166e7550d64239cd997a35e396c
master 分支實際上只是一個指向特定提交對象的指針。這種設計使得分支創建和切換非常高效。
git cat-file -p ec8c05d08dbd2166e7550d64239cd997a35e396c
git cat-file
命令可以查看 Git 對象的內容。這是深入了解 Git 內部工作原理的強大工具。
[root@VM-4-8-centos gitstudy]# git cat-file -p ec8c05d08dbd2166e7550d64239cd997a35e396c
tree 9c7b41e1c03f5499d21419108d6ef57d0bec1da4
author sin <123456@sin.com> 1747633828 +0800
committer sin <123456@sin.com> 1747633828 +0800Init and test
這個提交對象包含了指向樹對象(tree)的指針、作者信息、提交者信息和提交消息。樹對象則包含了項目目錄結構和文件指針。
git追蹤管理的不是文件,是修改。這意味著 Git 關注的是內容的變化,而不是文件本身。這種設計使得 Git 能夠高效地處理文件重命名、移動等操作。
查看狀態與差異
git status
git status
是日常使用最頻繁的命令之一。它會告訴你:
- 哪些文件被修改但未暫存
- 哪些文件已暫存準備提交
- 當前所在的分支
- 與遠程分支的關系
[root@VM-4-8-centos gitstudy]# touch file1
[root@VM-4-8-centos gitstudy]# ls
file1 readme
[root@VM-4-8-centos gitstudy]# git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# file1
nothing added to commit but untracked files present (use "git add" to track)
這個輸出顯示我們創建了一個新文件 file1,但它目前處于"未跟蹤"狀態,意味著 Git 還沒有開始跟蹤它的變化。
使用git diff,可以查看文件的修改:
[root@VM-4-8-centos gitstudy]# git diff readme
diff --git a/readme b/readme
index 2f96a52..f633a22 100644
--- a/readme
+++ b/readme
@@ -1 +1,2 @@sdsadsad
+nihao
git diff
顯示工作區與暫存區之間的差異。這個輸出顯示我們在 readme 文件中添加了一行"nihao"。
版本回退
git reset [--soft | --mixed | --hard] [HEAD]
版本回退是 Git 的強大功能之一,但需要謹慎使用。三種模式的區別:
--soft
: 只移動 HEAD 指針,不改變暫存區和工作區--mixed
(默認): 移動 HEAD 指針并重置暫存區,但不改變工作區--hard
: 徹底回退,移動 HEAD 指針、重置暫存區和工作區
要慎用hard,防止一次回退導致代碼消失。使用 --hard
前,確保你已經保存或提交了所有重要更改。
回退一次之后,如何ID沒有被清楚,還是有后悔藥可以吃的(撤回回退)
使用git reflog可以查看回退操作。git reflog
記錄了 HEAD 的所有變化,即使是被"丟失"的提交也能在這里找到。
撤銷修改
如果在工作區中,可以使用下面的代碼進行撤銷修改:
- 手動修改
- Git checkout – [filename]
git checkout -- <file>
會丟棄工作區中指定文件的所有修改,將其恢復到最近一次提交或暫存的狀態。
如果代碼同時在工作區與暫存區,需要使用git reset進行版本回退。這種情況下,你需要先取消暫存(git reset HEAD <file>
),然后再撤銷工作區的修改。
刪除文件
Git提供刪除命令,可以同時刪除工作區與暫存區。
git rm
git rm
不僅會從工作目錄中刪除文件,還會將這次刪除操作記錄到暫存區。這與直接刪除文件后運行 git add
效果相同。
分支管理
分支是 Git 最強大的功能之一。Head可以指向其他分支,被指向的分支是當前工作的分支。
創建分支:
git branch dev
分支在 Git 中非常輕量級 - 它們只是指向特定提交的指針。創建新分支不會復制任何文件,只是創建一個新的指針。
切換分支:
git checkout dev
切換分支會更新工作目錄中的文件以匹配該分支指向的提交。如果工作區有未提交的修改,Git 會阻止切換以避免數據丟失。
查看當前分支:
git branch
不帶參數的 git branch
會列出所有本地分支,并在當前分支前標記星號。
合并操作:
在轉到master分支上后運行下面的代碼,即可將dev分支合并到master分支上。
git merge dev
合并將另一個分支的修改整合到當前分支。Git 會嘗試自動合并,如果遇到沖突,需要手動解決。
刪除本地分支:
git branch -d dev
刪除分支前,確保它的所有修改都已經合并到其他分支。如果分支未合并,Git 會拒絕刪除,除非使用 -D
強制刪除。
git中如果兩個分支產生沖突,會在生成的項目中顯示出來,之后由開發人員手動修復沖突。沖突標記格式為:
<<<<<<< HEAD
當前分支的內容
=======
要合并的分支的內容
>>>>>>> branch-name
在手動合并之后,需要進行一次提交操作。這個提交就是合并提交,記錄了沖突解決的結果。
在git中,可以將提交過程展示為可視的圖:
git log --graph --abbrev-commit
--graph
選項會繪制 ASCII 圖形展示分支和合并歷史,--abbrev-commit
顯示縮寫的提交哈希,使輸出更簡潔。
分支管理策略
FastForward模式下面,并不能看出來這次的提交是正常提交還是通過merge的提交。當合并的分支是當前分支的直接祖先時,Git 默認會使用"快進"(fast-forward)合并,即簡單移動分支指針而不創建合并提交。要強制創建合并提交,可以使用 --no-ff
選項。
遠程倉庫操作
從本地將代碼上傳到遠程倉庫:
git push
git push
將本地分支的提交上傳到遠程倉庫。第一次推送時需要使用 -u
選項設置上游分支。
將遠程倉庫拉去到本地:
git fetch
git fetch
從遠程倉庫下載所有數據,但不會自動合并到工作分支。這讓你可以在合并前先檢查變化。
git pull origin master:master
git pull
實際上是 git fetch
和 git merge
的組合操作。它會從遠程倉庫獲取最新更改并嘗試合并到當前分支。
如果遠端和本地的名稱一樣的話也可以使用下面的縮寫版:
git pull origin master
Git 別名
git除了可以配置name和email,也可以為命令起別名:
git config --global alias.lpa 'log --pretty=oneline --abbrev-commit'
別名可以顯著提高工作效率。例如,上面的命令創建了一個 lpa
別名,可以顯示簡潔的提交歷史。
標簽管理
可以對一次commit進行標簽的標識。標簽通常用于標記發布版本(v1.0, v2.0等)。
使用下面的命令,可以默認為最新的提交打一個標簽:
git tag v1.0
標簽分為輕量標簽(只是一個指向特定提交的指針)和附注標簽(包含打標簽者信息、日期和消息)。要創建附注標簽,使用 -a
選項。
使用下面的命令可以查看現在有哪些標簽存在:
git tag
在標簽命令之后也可以進行評論。使用 -m
選項可以為標簽添加注釋,這對發布說明特別有用。
可以用下面的代碼刪除標簽:
git tag -d v1.0
標簽默認只在本地創建,要共享標簽到遠程倉庫,需要顯式推送(git push origin v1.0
)。
總結
Git 是一個功能強大且靈活的工具,掌握它可以顯著提高你的開發效率。建議從基礎命令開始練習,逐步熟悉更高級的功能。記住:
- 頻繁提交,保持提交的原子性
- 編寫有意義的提交信息
- 合理使用分支進行功能開發
- 定期與遠程倉庫同步
隨著經驗的積累,你會越來越欣賞 Git 的設計哲學和強大能力。