Git 是目前最流行的分布式版本控制系統,被廣泛應用于軟件開發中。本文將全面介紹 Git 的各種功能和使用方法,包含大量代碼示例和實踐建議。
文章目錄
- Git 基礎概念
- 版本控制系統
- Git 的特點
- Git 的三個區域
- Git 文件狀態
- Git 安裝與配置
- 安裝 Git
- Linux
- macOS
- Windows
- 初始配置
- Git 倉庫創建與管理
- 初始化新倉庫
- 克隆現有倉庫
- 查看倉庫狀態
- 忽略文件
- Git 基本工作流程
- 添加文件到暫存區
- 提交更改
- 查看提交歷史
- 比較差異
- Git 分支管理
- 創建與切換分支
- 合并分支
- 解決沖突
- 變基 (Rebase)
- Git 遠程倉庫操作
- 查看遠程倉庫
- 添加/移除遠程倉庫
- 獲取與拉取
- 推送
- Git 撤銷與回退
- 撤銷工作目錄修改
- 撤銷暫存區修改
- 修改最后一次提交
- 回退提交
- 恢復刪除的文件
- Git 標簽管理
- 創建標簽
- 查看標簽
- 推送標簽
- 刪除標簽
- 檢出標簽
- Git 高級操作
- 儲藏更改
- 二分查找
- 子模塊
- 重寫歷史
- 打包與歸檔
- Git 協作工作流
- 集中式工作流
- 功能分支工作流
- Git Flow
- Forking 工作流
- Git 問題排查
- 查看文件修改歷史
- 查找問題提交
- 恢復丟失的提交
- 清理倉庫
- Git 最佳實踐
- 提交規范
- 分支命名規范
- 工作流程建議
- 大型項目建議
- 安全性建議
- 總結

Git 基礎概念
版本控制系統
版本控制系統 (Version Control System, VCS) 是記錄文件內容變化,以便將來查閱特定版本修訂情況的系統。
Git 的特點
- 分布式:每個開發者都有完整的倉庫副本
- 高效:大部分操作在本地完成
- 完整性:使用 SHA-1 哈希保證數據完整性
- 靈活性:支持多種非線性開發流程
Git 的三個區域
- 工作目錄 (Working Directory):實際文件所在目錄
- 暫存區 (Staging Area):準備提交的文件快照
- Git 倉庫 (Repository):永久存儲的文件快照
Git 文件狀態
- 未跟蹤 (Untracked):新文件,未被 Git 管理
- 已修改 (Modified):文件已修改但未暫存
- 已暫存 (Staged):文件已修改并標記為下次提交
- 已提交 (Committed):文件已安全保存在本地數據庫
Git 安裝與配置
安裝 Git
Linux
# Debian/Ubuntu
sudo apt-get install git# Fedora
sudo dnf install git# CentOS
sudo yum install git
macOS
# 使用 Homebrew
brew install git# 或下載官方安裝包
https://git-scm.com/download/mac
Windows
下載 Git for Windows: https://git-scm.com/download/win
初始配置
配置用戶信息:
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
配置默認編輯器:
git config --global core.editor "vim"
查看配置:
git config --list
常用別名配置:
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
Git 倉庫創建與管理
初始化新倉庫
mkdir my-project
cd my-project
git init
克隆現有倉庫
git clone https://github.com/user/repo.git
git clone https://github.com/user/repo.git my-local-folder # 指定本地目錄名
git clone --depth 1 https://github.com/user/repo.git # 淺克隆,只獲取最新版本
查看倉庫狀態
git status
git status -s # 簡潔輸出
忽略文件
創建 .gitignore
文件:
# 忽略所有 .a 文件
*.a# 但跟蹤所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a# 忽略當前目錄下的 TODO 文件
/TODO# 忽略 build/ 目錄下的所有文件
build/# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt# 忽略 doc/ 目錄下所有 .pdf 文件
doc/**/*.pdf# 忽略所有 .log 文件
*.log# 忽略 node_modules 目錄
node_modules/# 忽略 .env 環境文件
.env
Git 基本工作流程
添加文件到暫存區
git add file1.txt # 添加單個文件
git add file2.txt file3.txt # 添加多個文件
git add . # 添加所有修改和新文件
git add -A # 添加所有修改、新文件和刪除操作
git add -u # 添加所有修改和刪除,但不包括新文件
git add -p # 交互式添加
提交更改
git commit -m "Initial commit" # 簡單提交
git commit -a -m "Commit all changes" # 跳過暫存區,直接提交所有已跟蹤文件的修改
git commit --amend # 修改最后一次提交
git commit --amend --no-edit # 修改最后一次提交但不修改提交信息
查看提交歷史
git log
git log -p # 顯示每次提交的內容差異
git log -2 # 顯示最近2次提交
git log --stat # 顯示簡略統計信息
git log --pretty=oneline # 單行顯示
git log --pretty=format:"%h - %an, %ar : %s"
git log --since=2.weeks # 顯示兩周內的提交
git log --author="John" # 按作者篩選
git log --grep="bug fix" # 按提交信息篩選
git log -S"function_name" # 按代碼內容篩選
git log -- path/to/file # 查看特定文件的修改歷史
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit # 漂亮的圖形化輸出
比較差異
git diff # 工作目錄與暫存區的差異
git diff --staged # 暫存區與最后一次提交的差異
git diff HEAD # 工作目錄與最后一次提交的差異
git diff branch1..branch2 # 兩個分支間的差異
git diff commit1 commit2 # 兩次提交間的差異
git diff --name-only commit1 commit2 # 只顯示有差異的文件名
git diff --word-diff # 單詞級別的差異
Git 分支管理
創建與切換分支
git branch # 查看本地分支
git branch -a # 查看所有分支(包括遠程)
git branch new-branch # 創建新分支
git checkout branch-name # 切換分支
git checkout -b new-branch # 創建并切換到新分支
git checkout -b new-branch origin/remote-branch # 基于遠程分支創建本地分支
git branch -d branch-name # 刪除已合并的分支
git branch -D branch-name # 強制刪除分支
git branch -m old-name new-name # 重命名分支
git branch --merged # 查看已合并到當前分支的分支
git branch --no-merged # 查看未合并到當前分支的分支
合并分支
git merge branch-name # 合并指定分支到當前分支
git merge --no-ff branch-name # 禁用快進合并
git merge --squash branch-name # 壓縮合并
git merge --abort # 中止合并
解決沖突
當合并發生沖突時,Git 會在沖突文件中標記沖突部分:
<<<<<<< HEAD
當前分支的內容
=======
要合并的分支的內容
>>>>>>> branch-name
手動解決沖突后:
git add resolved-file.txt
git commit
變基 (Rebase)
git rebase branch-name # 將當前分支變基到指定分支
git rebase --continue # 解決沖突后繼續變基
git rebase --abort # 中止變基
git rebase -i HEAD~3 # 交互式變基,修改最近3次提交
交互式變基常用操作:
- pick: 使用提交
- reword: 使用提交但修改提交信息
- edit: 使用提交但暫停修改
- squash: 將提交合并到前一個提交
- fixup: 類似 squash 但丟棄提交信息
- drop: 刪除提交
Git 遠程倉庫操作
查看遠程倉庫
git remote # 列出遠程倉庫
git remote -v # 顯示遠程倉庫URL
git remote show origin # 顯示遠程倉庫詳細信息
添加/移除遠程倉庫
git remote add origin https://github.com/user/repo.git # 添加遠程倉庫
git remote rename origin new-name # 重命名遠程倉庫
git remote remove origin # 移除遠程倉庫
git remote set-url origin https://github.com/user/new-repo.git # 修改遠程倉庫URL
獲取與拉取
git fetch origin # 從遠程獲取最新信息但不合并
git fetch --prune # 清理已不存在的遠程分支的本地引用
git pull origin master # 獲取并合并遠程分支
git pull --rebase # 使用變基方式拉取
推送
git push origin master # 推送本地分支到遠程
git push -u origin master # 推送并設置上游分支
git push origin --delete branch-name # 刪除遠程分支
git push origin --tags # 推送所有標簽
git push origin HEAD # 推送當前分支
git push --force # 強制推送(慎用)
git push --force-with-lease # 更安全的強制推送
Git 撤銷與回退
撤銷工作目錄修改
git checkout -- file.txt # 撤銷工作目錄中文件的修改
git checkout -- . # 撤銷所有工作目錄修改
撤銷暫存區修改
git reset HEAD file.txt # 將文件從暫存區移出
git reset HEAD . # 將所有文件從暫存區移出
修改最后一次提交
git commit --amend # 修改提交信息或內容
git commit --amend --no-edit # 修改提交內容但不修改信息
回退提交
git reset --soft HEAD~1 # 回退提交但保留修改在暫存區
git reset --mixed HEAD~1 # 回退提交并保留修改在工作目錄(默認)
git reset --hard HEAD~1 # 徹底回退提交,丟棄所有修改
git revert HEAD # 創建新提交來撤銷之前的提交
恢復刪除的文件
git checkout HEAD -- deleted-file.txt # 恢復已刪除的文件
git checkout $(git rev-list -n 1 HEAD -- deleted-file.txt)^ -- deleted-file.txt # 恢復在之前提交中刪除的文件
Git 標簽管理
創建標簽
git tag v1.0 # 輕量標簽
git tag -a v1.0 -m "Version 1.0" # 附注標簽
git tag -a v1.0 9fceb02 # 給特定提交打標簽
git tag -s v1.0 -m "Signed version 1.0" # 簽名標簽
查看標簽
git tag # 列出所有標簽
git show v1.0 # 查看標簽詳情
git tag -l "v1.*" # 過濾標簽
推送標簽
git push origin v1.0 # 推送單個標簽
git push origin --tags # 推送所有標簽
刪除標簽
git tag -d v1.0 # 刪除本地標簽
git push origin --delete v1.0 # 刪除遠程標簽
git push origin :refs/tags/v1.0 # 另一種刪除遠程標簽的方式
檢出標簽
git checkout v1.0 # 檢出標簽(進入分離頭指針狀態)
git checkout -b version1 v1.0 # 基于標簽創建新分支
Git 高級操作
儲藏更改
git stash # 儲藏當前工作目錄和暫存區的修改
git stash save "message" # 帶消息的儲藏
git stash list # 列出所有儲藏
git stash apply # 應用最近的儲藏
git stash apply stash@{1} # 應用特定儲藏
git stash pop # 應用并移除最近的儲藏
git stash drop stash@{1} # 刪除特定儲藏
git stash clear # 清除所有儲藏
git stash branch new-branch # 從儲藏創建新分支
git stash -u # 儲藏包括未跟蹤文件
git stash -a # 儲藏包括所有文件(包括.gitignore忽略的)
二分查找
git bisect start # 開始二分查找
git bisect bad # 當前版本有問題
git bisect good v1.0 # v1.0版本是好的
git bisect reset # 結束二分查找
git bisect run test-script.sh # 自動運行測試腳本進行二分查找
子模塊
git submodule add https://github.com/user/repo.git path/to/submodule # 添加子模塊
git submodule init # 初始化子模塊
git submodule update # 更新子模塊
git submodule update --init --recursive # 遞歸初始化并更新所有子模塊
git submodule foreach 'git checkout master' # 對所有子模塊執行命令
git clone --recurse-submodules https://github.com/user/repo.git # 克隆包含子模塊的倉庫
重寫歷史
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD # 從所有提交中刪除文件
git filter-branch --commit-filter 'if [ "$GIT_AUTHOR_EMAIL" = "old@email.com" ];thenGIT_AUTHOR_NAME="New Name";GIT_AUTHOR_EMAIL="new@email.com";git commit-tree "$@";elsegit commit-tree "$@";fi' HEAD # 修改作者信息
注意:重寫歷史會改變提交哈希,只適用于尚未共享的提交。
打包與歸檔
git bundle create repo.bundle HEAD master # 創建包含master分支的bundle文件
git clone repo.bundle repo -b master # 從bundle文件克隆
git archive --format=zip HEAD > archive.zip # 創建當前提交的zip歸檔
git archive --format=tar --prefix=project/ HEAD | gzip > project.tar.gz # 創建帶前綴的tar.gz歸檔
Git 協作工作流
集中式工作流
- 開發者克隆中央倉庫
- 在本地提交更改
- 推送更改到中央倉庫
- 解決沖突(如果有)
功能分支工作流
- 為每個新功能創建獨立分支
- 在功能分支上開發
- 完成后合并到主分支
- 刪除功能分支
git checkout -b new-feature
# 開發功能...
git commit -a -m "Implement new feature"
git checkout master
git merge new-feature
git branch -d new-feature
Git Flow
Git Flow 是一種流行的分支模型,定義嚴格的分支角色和交互方式。
主要分支:
- master: 生產代碼
- develop: 集成開發分支
支持分支:
- feature/*: 功能開發分支
- release/*: 準備發布分支
- hotfix/*: 緊急修復分支
# 初始化Git Flow
git flow init# 開始新功能
git flow feature start myfeature# 完成功能
git flow feature finish myfeature# 發布新版本
git flow release start 1.0.0
git flow release finish 1.0.0# 緊急修復
git flow hotfix start 1.0.1
git flow hotfix finish 1.0.1
Forking 工作流
- 開發者fork中央倉庫
- 克隆自己的fork到本地
- 創建功能分支開發
- 推送更改到自己的fork
- 創建Pull Request請求合并到中央倉庫
# 克隆fork的倉庫
git clone https://github.com/yourname/repo.git# 添加上游倉庫
git remote add upstream https://github.com/original/repo.git# 獲取上游更改
git fetch upstream
git merge upstream/master# 創建功能分支
git checkout -b new-feature# 開發完成后推送到自己的fork
git push origin new-feature# 然后在GitHub上創建Pull Request
Git 問題排查
查看文件修改歷史
git blame file.txt # 查看文件的逐行修改歷史
git blame -L 10,20 file.txt # 查看特定行的修改歷史
git log -p file.txt # 查看文件的完整修改歷史
git show commit-id:file.txt # 查看特定提交中的文件內容
查找問題提交
git bisect start # 開始二分查找
git bisect bad # 標記當前版本有問題
git bisect good v1.0 # 標記v1.0版本是好的
# Git會自動檢出中間版本,你測試后標記good或bad
git bisect reset # 結束二分查找
恢復丟失的提交
git reflog # 查看所有HEAD指向的歷史
git fsck --lost-found # 查找懸空對象
git show commit-id # 檢查找到的提交
git merge commit-id # 恢復丟失的提交
清理倉庫
git gc # 清理不必要的文件并優化本地倉庫
git clean -n # 顯示將被刪除的未跟蹤文件(干跑)
git clean -f # 刪除未跟蹤文件
git clean -fd # 刪除未跟蹤文件和目錄
git prune # 刪除懸空對象
Git 最佳實踐
提交規范
- 提交信息應清晰描述修改內容
- 第一行不超過50字符,作為摘要
- 第二行空行
- 第三行開始詳細說明(如有必要)
- 使用現在時態、命令語氣(如"Fix bug"而非"Fixed bug")
示例:
Summarize changes in around 50 characters or lessMore detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of the commit and the rest of the text as the body. The
blank line separating the summary from the body is critical (unless
you omit the body entirely); various tools like `log`, `shortlog`
and `rebase` can get confused if you run the two together.Explain the problem that this commit is solving. Focus on why you
are making this change as opposed to how (the code explains that).
Are there side effects or other unintuitive consequences of this
change? Here's the place to explain them.Further paragraphs come after blank lines.- Bullet points are okay, too- Typically a hyphen or asterisk is used for the bullet, precededby a single space, with blank lines in between, but conventionsvary here
分支命名規范
- feature/*: 新功能開發
- bugfix/*: 錯誤修復
- hotfix/*: 緊急修復
- release/*: 版本發布準備
- docs/*: 文檔更新
- test/*: 測試相關
工作流程建議
- 頻繁提交,原子性提交(每個提交只做一件事)
- 在推送前整理本地提交歷史
- 使用分支進行功能開發和問題修復
- 定期從上游拉取更改
- 使用Pull Request進行代碼審查
大型項目建議
- 使用子模塊或子樹管理依賴
- 使用淺克隆減少下載量
- 使用稀疏檢出只獲取需要的文件
- 使用Git LFS管理大文件
# 淺克隆
git clone --depth 1 https://github.com/user/repo.git# 稀疏檢出
git init repo
cd repo
git remote add origin https://github.com/user/repo.git
git config core.sparseCheckout true
echo "some/dir/" >> .git/info/sparse-checkout
git pull origin master
安全性建議
- 不要提交敏感信息(密碼、密鑰等)
- 使用.gitignore忽略不必要的文件
- 定期檢查提交歷史中的敏感信息
- 必要時重寫歷史刪除敏感信息
# 檢查歷史中是否包含敏感信息
git log -p | grep "password"
總結
Git 是一個功能強大且靈活的工具,掌握它可以極大提高開發效率。本文涵蓋了 Git 的各個方面,從基礎操作到高級技巧,從個人使用到團隊協作。建議讀者在實際項目中多加練習,逐步掌握 Git 的各種功能。
記住,Git 的核心概念是快照而非差異,理解這一點有助于更好地使用 Git。同時,遵循最佳實踐可以使版本控制更加高效和安全。
Git 的學習曲線可能較陡峭,但一旦掌握,它將成為你開發工作中不可或缺的利器。