Git 使用全指南
第一部分:核心概念
-
什么是 Git?
- 一个分布式版本控制系统 (DVCS)。
- 目标: 跟踪文件变化、协作开发、回溯历史、管理不同开发线(分支)。
- 核心思想: 每个开发者都有完整的仓库副本(包括完整历史),不依赖中央服务器也能工作。
-
关键概念:
- 仓库 (Repository / Repo): 项目的根目录,包含所有文件及其历史记录。
.git
隐藏文件夹就是本地仓库的核心。 - 工作区 (Working Directory / Working Tree): 你在电脑上看到的项目目录,是你实际编辑文件的地方。
- 暂存区 (Staging Area / Index): 一个中间区域。你把准备提交的更改
git add
到这里。它像是一个“准备就绪”的清单。 - 提交 (Commit): 一个永久的快照,记录了暂存区在某个时间点的状态。每个提交有唯一的 ID (SHA-1 哈希值)、作者、时间戳和提交信息。
- 分支 (Branch): 指向某个提交的轻量级指针。默认分支通常是
master
或main
。创建分支是为了隔离开发(如新功能、Bug 修复)。 - HEAD: 一个特殊的指针,指向你当前所在的分支(或具体的提交,在
detached HEAD
状态时)。它代表你当前的工作位置。 - 远程 (Remote): 托管在服务器(如 GitHub, GitLab, Gitee)上的仓库副本,用于团队协作和备份。常见默认远程名称为
origin
。 - 克隆 (Clone): 从远程仓库创建一个完整的本地仓库副本,包括所有历史记录和分支。
- 拉取 (Pull):
git pull
=git fetch
(获取远程最新数据) +git merge
(尝试将远程分支合并到当前本地分支)。 - 推送 (Push): 将本地分支的提交上传到远程仓库。
- 合并 (Merge): 将一个分支的更改整合到另一个分支。通常会创建一个新的“合并提交”。
- 变基 (Rebase): 将当前分支的提交“重新播放”在另一个分支(通常是更新的基础分支)的最新提交之上。可以使历史线更清晰(线性),但需谨慎使用在共享分支上。
- 冲突 (Conflict): 当 Git 无法自动合并不同分支对同一文件的同一部分所做的更改时发生。需要手动解决。
- 仓库 (Repository / Repo): 项目的根目录,包含所有文件及其历史记录。
第二部分:安装与配置
-
安装:
- Windows: 下载官方安装程序: https://git-scm.com/download/win
- macOS:
- 安装 Xcode Command Line Tools (在终端运行
xcode-select --install
) - 或使用 Homebrew:
brew install git
- 安装 Xcode Command Line Tools (在终端运行
- Linux (Debian/Ubuntu):
sudo apt update && sudo apt install git
- Linux (Fedora):
sudo dnf install git
-
首次配置 (重要!):
# 设置你的用户名 (提交者标识) git config --global user.name "你的名字" # 设置你的邮箱 (提交者标识) git config --global user.email "你的邮箱@example.com" # 设置默认文本编辑器 (用于写提交信息,如 vim, nano, code) git config --global core.editor "code --wait" # 使用 VS Code # 启用有帮助的颜色输出 git config --global color.ui auto # 设置默认分支名称为 main (可选,推荐) git config --global init.defaultBranch main
--global
选项表示这些设置应用于你系统上的所有仓库。如果想为特定仓库设置不同信息,在仓库目录下运行去掉--global
的命令。
第三部分:基础操作 - 本地工作流
-
创建新仓库:
mkdir my-project # 创建项目目录 cd my-project # 进入目录 git init # 初始化 Git 仓库 (创建 .git 文件夹)
-
克隆现有仓库:
git clone https://github.com/username/repository.git [可选:新目录名] # 例如: git clone https://github.com/octocat/Spoon-Knife.git
-
检查状态:
git status # 查看工作区和暂存区的状态 (哪些文件修改了/新增了/准备提交了)
-
跟踪新文件 / 暂存更改:
git add <file1> <file2> ... # 添加特定文件到暂存区 git add . # 添加当前目录下所有更改 (包括新文件、修改的文件) 到暂存区 (谨慎使用,确保不要添加不需要的文件) git add -A # 添加工作区中所有更改 (包括新文件、修改的文件、删除的文件) 到暂存区 git add -p # 交互式暂存,允许你选择性地暂存文件中的部分更改 (非常有用!)
-
提交更改:
git commit # 打开配置的编辑器编写提交信息 git commit -m "提交信息" # 直接在命令行写提交信息
- 提交信息规范: 清晰、简洁。第一行写简短摘要(<50字符),空一行,然后写详细说明(为什么改,改了啥)。参考 Conventional Commits 或 Angular 规范。
-
查看历史:
git log # 查看完整提交历史 git log --oneline # 查看简洁的历史 (每个提交一行) git log --graph # 以 ASCII 图显示分支和合并历史 git log --author="名字" # 查看特定作者的提交 git log -p <file> # 查看某个文件的详细修改历史 git show <commit-id> # 查看某个特定提交的详细信息
-
忽略文件 (.gitignore):
- 创建名为
.gitignore
的文件在仓库根目录。 - 列出你不想 Git 跟踪的文件或目录模式 (每行一个)。
- 示例:
# 忽略所有 .log 文件 *.log # 忽略特定文件 secret.key # 忽略 build/ 目录下的所有内容 build/ # 但不要忽略 build/important.lib (例外) !build/important.lib
- 使用模板: https://github.com/github/gitignore
- 创建名为
第四部分:分支管理
-
创建分支:
git branch <branch-name> # 创建新分支 (基于当前 HEAD) git checkout -b <branch-name> # 创建并立即切换到新分支 (常用)
-
切换分支:
git checkout <branch-name> # 切换到现有分支 git switch <branch-name> # (Git 2.23+) 更明确的切换分支命令 (推荐)
-
列出分支:
git branch # 列出本地分支 (* 号标出当前分支) git branch -a # 列出所有分支 (包括远程分支 remote/<branch-name>) git branch -v # 列出分支并显示每个分支的最后一次提交
-
删除分支:
git branch -d <branch-name> # 删除已合并的分支 (安全) git branch -D <branch-name> # 强制删除未合并的分支 (谨慎!)
-
合并分支:
- 切换到你想合并到的目标分支 (通常是
main
/master
或develop
):git switch main
- 执行合并:
git merge <branch-to-merge> # 例如: git merge feature/login
- 如果发生冲突:
git status
会显示冲突文件。- 手动编辑这些文件,解决冲突(删除
<<<<<<<
,=======
,>>>>>>>
标记,保留你想要的代码)。 - 使用
git add <resolved-file>
将解决后的文件标记为已解决。 - 所有冲突解决后,执行
git commit
完成合并提交。
- 切换到你想合并到的目标分支 (通常是
-
变基 (Rebase):
- 目的: 使当前分支的历史看起来像是基于目标分支的最新提交开发的(更线性)。
- 操作 (在当前分支上执行):
git rebase <target-branch> # 例如 (在 feature 分支上): git rebase main
- 如果发生冲突:
- 解决冲突(同合并)。
git add <resolved-file>
。- 不要
git commit
! 使用git rebase --continue
。 - 如果想放弃变基:
git rebase --abort
。
- 黄金法则: 不要对你仓库之外有副本的分支(即已推送到远程并被他人使用的分支)执行变基!变基会重写历史。
-
比较差异 (Diff):
git diff # 工作区 vs 暂存区 (未暂存的更改) git diff --staged (或 --cached) # 暂存区 vs 最新提交 (已暂存的更改) git diff <commit1> <commit2> # 比较两个提交 git diff <branch1>..<branch2> # 比较两个分支的尖端
第五部分:远程协作
-
查看远程仓库:
git remote -v # 查看远程仓库的 URL (fetch/push)
-
添加远程仓库:
git remote add <remote-name> <url> # 例如: git remote add origin https://github.com/you/repo.git
-
从远程获取更新:
git fetch <remote-name> # 例如: git fetch origin (下载远程所有分支和提交,但不修改你的工作区) git fetch --prune # 同时删除本地已不存在的远程分支的跟踪引用
-
拉取远程更改:
git pull <remote-name> <branch-name> # 例如: git pull origin main # 相当于 git fetch origin + git merge origin/main (到当前分支) git pull --rebase # 使用 rebase 代替 merge 进行拉取 (更干净的本地历史)
-
推送本地更改到远程:
git push <remote-name> <branch-name> # 例如: git push origin feature/login git push -u origin <branch-name> # 首次推送时设置上游跟踪 (-u / --set-upstream), 之后可以直接 `git push` git push # 如果上游已设置,推送当前分支 git push --force (或 -f) # 强制推送 (重写远程历史!极其危险,仅在你完全清楚后果时使用)
-
跟踪远程分支:
- 克隆或
git fetch
后,你会看到origin/main
这样的远程分支引用。 - 要基于远程分支创建本地跟踪分支:
git switch --track origin/<branch-name> # (Git 2.23+) # 或旧方式 git checkout -b <local-branch-name> origin/<remote-branch-name> git branch -u origin/<remote-branch-name> # 设置现有本地分支的上游
- 克隆或
第六部分:撤销与回退
-
撤销工作区的修改 (未
git add
):git restore <file> # (Git 2.23+) 丢弃工作区中指定文件的修改 (回到最近一次 `git add` 或 `git commit` 的状态) # 旧方式 (仍有效): git checkout -- <file>
-
撤销暂存区的修改 (已
git add
, 未git commit
):git restore --staged <file> # (Git 2.23+) 将文件从暂存区移回工作区 (取消暂存) # 旧方式: git reset HEAD <file>
-
修改最后一次提交:
git commit --amend # 修改提交信息或加入漏掉的文件 (先 `git add` 漏掉的文件) # 注意:这会创建新的提交ID,如果已推送,需谨慎并可能需要强制推送 (不推荐在已推送后修改)
-
回退到某个提交 (创建新提交撤销更改):
git revert <commit-id> # 创建一个新的提交,撤销指定提交引入的更改。安全,适用于已推送的提交。
-
重置到某个提交 (危险!会丢弃历史):
git reset --soft <commit-id> # 移动 HEAD 和分支指针到目标提交,保留工作区和暂存区的更改 (像是撤销了 commit) git reset --mixed <commit-id> # (默认) 移动 HEAD 和分支指针,重置暂存区到目标提交状态,保留工作区更改 (像是撤销了 commit 和 add) git reset --hard <commit-id> # 移动 HEAD 和分支指针,重置暂存区和工作区到目标提交状态。**丢弃所有之后的更改!** 极其危险,慎用!
- 警告:
git reset --hard
会永久删除未提交的工作区更改和未推送的提交。仅用于本地未推送的提交回退。
- 警告:
-
找回丢失的提交/分支:
- 使用
git reflog
查看 HEAD 和分支的引用变更历史。找到丢失的提交 ID。 - 基于找到的提交 ID 创建新分支:
git branch recovered-branch <commit-id>
- 使用
第七部分:高级技巧与最佳实践
-
储藏 (Stash): 临时保存工作区和暂存区的更改,以便清理现场去处理其他事情(如切换分支修复紧急 Bug)。
git stash # 储藏当前更改 git stash push -m "message" # 储藏并添加信息 git stash list # 列出储藏栈 git stash apply [stash@{n}] # 应用最近的储藏 (或指定储藏),不删除储藏 git stash pop [stash@{n}] # 应用并删除最近的储藏 (或指定储藏) git stash drop [stash@{n}] # 删除指定的储藏 git stash clear # 清空整个储藏栈
-
标签 (Tag): 为重要的提交(如版本发布 v1.0.0)打上永久标记。
git tag -a v1.0.0 -m "Release version 1.0.0" <commit-id> # 创建带注释的标签 (推荐) git tag v1.0.0-lightweight # 创建轻量标签 (无额外信息) git tag # 列出标签 git show v1.0.0 # 显示标签信息 git push origin v1.0.0 # 推送特定标签到远程 git push origin --tags # 推送所有标签到远程
-
子模块 (Submodule): 在一个 Git 仓库中包含另一个 Git 仓库。
- 添加:
git submodule add <repository-url> <path>
- 克隆包含子模块的仓库:
git clone --recurse-submodules <repository-url>
- 更新子模块:
git submodule update --init --recursive
- 添加:
-
.gitconfig
别名: 创建常用命令的快捷方式。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 'restore --staged --' # (Git 2.23+) 取消暂存 git config --global alias.last 'log -1 HEAD' # 查看最后一次提交
之后可以用
git co
,git br
,git ci
,git st
,git unstage <file>
,git last
。 -
工作流 (Workflow):
- 集中式工作流 (Centralized): 类似 SVN,所有人在
main
分支上直接提交/拉取/推送。简单但容易冲突。 - 功能分支工作流 (Feature Branch): 最常用。每个新功能/修复在独立分支开发,完成后通过 Pull Request (PR) / Merge Request (MR) 请求合并到
main
/develop
。 - Gitflow: 更结构化的分支模型,定义了
main
(生产),develop
(集成分支),feature/*
,release/*
,hotfix/*
等分支角色。适合有严格发布流程的项目。 - Forking 工作流: 常用于开源项目。开发者 Fork 主仓库到自己的账户,在 Fork 的仓库中开发,然后向主仓库发起 PR。主仓库维护者审核并合并。
- 集中式工作流 (Centralized): 类似 SVN,所有人在
-
Pull Request / Merge Request (PR/MR):
- 不是 Git 核心命令,是 GitHub/GitLab 等平台提供的协作功能。
- 开发者推送功能分支到自己的远程仓库(或 Fork)。
- 在平台上发起 PR/MR,请求将源分支(你的功能分支)合并到目标分支(通常是上游的
main
/develop
)。 - 进行代码审查、讨论、自动化测试。
- 审查通过后由维护者合并。
第八部分:图形化工具 (GUI)
- 命令行 (
git
) 是最强大和通用的方式。 - GUI 工具可以提供更直观的界面查看历史、分支图、解决冲突等。常用工具包括:
- GitHub Desktop
- GitKraken
- Sourcetree
- VS Code 内置的 Git 功能 (非常强大)
- GitExtensions
- TortoiseGit (Windows 资源管理器集成)
第九部分:常见问题与陷阱
- 冲突: 不可避免,冷静处理。仔细阅读冲突标记,与队友沟通。
git push
失败 (非快进): 别人在你之前推送了更改。先git pull
(解决可能冲突),再git push
。避免使用--force
除非你完全理解后果。- 误删未提交的更改: 如果没
git add
, 通常很难恢复。养成频繁提交的习惯。 - 误删分支/提交: 尝试
git reflog
找回提交 ID,然后重建分支。 - 大文件: Git 不适合管理大文件(二进制、媒体文件)。使用 Git LFS (Large File Storage) 或
.gitignore
忽略它们。 .gitignore
不生效: 确保文件在忽略规则生效前没有被跟踪过。如果已被跟踪,需要先git rm --cached <file>
将其从 Git 中删除(保留本地文件),然后提交.gitignore
。
总结
掌握 Git 需要时间和实践。从基础命令 (clone
, add
, commit
, push
, pull
, status
, log
, branch
, checkout/switch
) 开始,逐步学习分支操作 (merge
, rebase
)、撤销操作 (restore
, reset
, revert
)、远程协作和解决冲突。理解核心概念(工作区、暂存区、仓库、提交、分支、HEAD)是熟练运用的关键。选择合适的协作工作流(推荐功能分支+PR/MR)。善用 .gitignore
和 GUI 工具提高效率。遇到问题时,git status
和 git help <command>
是你的好朋友。
不断练习,你就能成为 Git 高手!