Featured image of post 理解 Git:终极指南

理解 Git:终极指南

一份全面、适合初学者的 Git 概念、命令和工作流指南,配有实用示例和清晰解释

思维模型:理解 Git 的核心概念

有没有觉得看 Git 文档像是在读象形文字?我也有过这种感受。让我们用更通俗的方式来拆解 Git。

Git 的大图景:一切都是副本

归根结底,Git 就是一个用来管理你代码不同副本的高级系统:

  • 远程副本:存放在服务器上(比如 GitHub、GitLab 或你们公司的服务器)
  • 本地副本:你电脑上的那份,你实际操作的代码

有趣的是:

虽然远程可以有很多不同的副本(分支),但你本地一次只会操作一个活跃的版本。

可以这样想:就像大学里小组写论文,“官方"版本存在共享的 Google Drive(远程),但每个人都有自己的本地副本在修改。Git 帮你管理这些版本如何同步。

仓库:你项目的家

仓库(Repository,简称 “repo”)就是所有这些副本及其历史的集合。每个仓库都有唯一的 URL(即 repo_url)。

比如 React 的仓库地址是 https://github.com/facebook/react.git —— 这就是它的 repo_url

用实际例子解释 Git 概念

什么是 “提交”(Commit)?

提交就像是在某个时间点给你的代码拍了一张快照。

可以把提交想象成电子游戏里的存档点。你取得了进展,想确保如果后面出问题,随时能回到这个状态。

示例场景:

1
2
3
# 你修改了代码
git add index.html styles.css
git commit -m "添加响应式头部并修复导航样式"

此时,你已经在本地保存了这个存档点,但远程仓库还不知道。所以我们需要推送(push)提交。

什么是 “Origin”?

因为每次输入完整的仓库 URL 太麻烦,Git 用像 “origin” 这样的别名来指代远程仓库。

“origin” 只是 Git 默认给你克隆仓库来源起的昵称。

实际例子:

1
2
3
4
5
6
7
8
9
# 当你克隆一个仓库
git clone https://github.com/your-username/cool-project.git

# Git 会自动把 "origin" 指向这个 URL
# 之后你只需要这样写:
git push origin main

# 而不用每次都输入长长的地址:
git push https://github.com/your-username/cool-project.git main

你还可以添加其他远程仓库,这在参与开源项目时很有用:

1
2
3
4
5
# 添加另一个远程仓库
git remote add upstream https://github.com/original-creator/cool-project.git

# 现在你可以从原始仓库获取更新
git fetch upstream

什么是 “分支”(Branch)?

很多 Git 教程在这里让人迷惑。我们来理清楚:

分支其实并不是真正意义上的树枝——更像是一个指针或标签,标记着某条开发时间线。

如果用树来比喻,branch(分支)其实更像叶子(时间才是树枝)

更清晰的理解方式:

想象你的项目时间线是一条铁轨。main 分支就是主轨道。当你创建新分支时,其实是在某个点插了个旗子,表示“我要从这里开始修一条新轨道”。

实际操作例子:

1
2
3
4
5
6
# 从 main 分支开始新功能分支
git checkout main
git checkout -b feature/user-authentication

# 现在你可以在不影响 main 的情况下修改代码
# 每次提交都会让 feature/user-authentication 指针向前移动

你在功能分支上的所有提交会形成一条独立的开发时间线,之后可以合并回主时间线。

什么是 “Fetch”?

git fetch 命令就像是去信箱查收新邮件,但还没拆开看。

fetch 时,Git 会下载远程仓库的最新信息,但不会把这些更改应用到你的工作区。

示例:

1
2
3
4
5
6
# 检查远程仓库是否有更新
git fetch origin

# 现在 Git 已经知道远程的变化,但还没应用
# 你可以用下面命令查看所有分支:
git branch -a

fetch 之后,你可以决定是否以及如何把这些更改合并到本地。

什么是 “Pull”?

git pull 是 fetch 和 merge 的组合:

1
git pull origin main = git fetch origin + git merge origin/main

就像你查收信箱并把信件带回家一起读。

常见场景:

1
2
3
4
# 开始一天工作,先拉取最新更改
git pull origin main

# 这会把队友们在你离开时推送的更改同步到你的本地 main 分支

但有时你可能想用 git pull --rebase,这就引出了下一个话题……

大战:“合并”(Merge) vs “变基”(Rebase)

这里是 Git 哲学之争,也是开发者争论最多的地方。让我用实际场景解释:

场景: 你在功能分支上开发了几天,这期间 main 分支被其他人推进了。

方案一:合并(Merge)

1
2
git checkout feature-branch
git merge main

合并会生成一个“合并提交”,把两个分支连在一起。历史记录会显示分支分开又合并的过程。

方案二:变基(Rebase)

1
2
git checkout feature-branch
git rebase main

变基会把你的更改“重放”到最新的 main 分支上。就像说:“假装我从现在的 main 开始做的这些更改。”

关键区别:

  • 合并:完整保留历史(分开又合并)
  • 变基:让历史更干净、线性(好像从没分过支)

什么时候用哪种:

  • 合并:适合公开/多人协作的分支
  • 变基:适合你自己的功能分支,在合并到 main 前使用

专业建议:在合并功能分支前,先变基到 main,这样历史最干净,也能减少合并冲突。

什么是 “暂存”(Stash)?

有没有遇到正在开发一半,突然要切去处理紧急任务,但又不想提交半成品?

这就是 git stash 的用武之地——就像把你的更改临时塞进抽屉,等会儿再处理。

实际场景:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 正在开发新功能,突然有紧急 bug 要修
# 先把当前更改暂存起来
git stash save "用户资料页半成品"

# 切换去修 bug
git checkout main
git checkout -b hotfix/critical-login-bug

# 修好 bug,提交并合并

# 回到你的功能分支
git checkout feature/user-profile
git stash list  # 查看所有暂存的更改
git stash apply stash@{0}  # 应用最新的暂存

# 用完某个 stash 后可以删除
git stash drop stash@{0}

可以把 stash 理解为可以贴到不同代码版本上的便签。

常见 Git 工作流

现在你已经了解了各个部分,让我们把它们串成一个典型的工作流:

功能分支工作流

  1. 保持最新:

    1
    2
    
    git checkout main
    git pull origin main
    
  2. 创建功能分支:

    1
    
    git checkout -b feature/awesome-new-thing
    
  3. 小步提交:

    1
    2
    3
    4
    5
    6
    7
    
    # 做一些更改
    git add -A
    git commit -m "实现 awesome 功能的第一部分"
    
    # 更多更改
    git add -A
    git commit -m "完成 awesome 功能"
    
  4. 与 main 保持同步:

    1
    2
    
    git fetch origin
    git rebase origin/main
    
  5. 推送你的分支:

    1
    
    git push origin feature/awesome-new-thing
    
  6. 创建 Pull Request(在 GitHub/GitLab 等平台)

  7. 审核通过后,合并或变基并合并

总结

刚接触 Git 时可能觉得复杂,但理解了它的思维模型后,一切都豁然开朗。记住:

  • 分支只是指向特定提交的指针
  • 提交是你代码在某一时刻的快照
  • 远程仓库存储着共享的历史
  • 本地仓库是你的个人工作区

最重要的是,和团队一起制定一套适合自己的工作流,并坚持执行。

还有哪些 Git 概念让你困惑?欢迎在评论区留言!