你真的会用Fork和分支吗

4020 字
20 分钟
你真的会用Fork和分支吗

你真的会用 Fork 和分支吗?#

很多人一开始学 Git 和 GitHub 的时候,会把 clone、fork、branch、merge、pull request 混在一起。它们确实经常一起出现,但本质上是不同层次的东西。 简单来说:

  • clone:把远程仓库复制到本地电脑。
  • fork:在 GitHub 上复制别人的仓库,变成你自己账号下的远程仓库。
  • branch:在同一个仓库里开一条新的开发线。
  • merge:把一个分支的修改合并到另一个分支。
  • pull request / PR:在 GitHub 上请求把你的修改合并到某个目标分支。

1. 先分清楚:本地仓库、自己的远程仓库、原始远程仓库#

假设有一个开源项目:

原始仓库:
github.com/original/project

你点击 GitHub 上的 Fork 之后,会得到一个你自己账号下的仓库:

你的 Fork 仓库:
github.com/yourname/project

然后你在本地执行:

Terminal window
git clone https://github.com/yourname/project.git

这时你电脑里会有一份本地仓库。 所以一个标准的 fork 工作流里,通常有三份仓库:

原始仓库 upstream:github.com/original/project
你的远程仓库 origin:github.com/yourname/project
你的本地仓库 local:你电脑上的 project 文件夹

其中:

  • upstream 通常表示原始仓库,也就是你 fork 的来源。
  • origin 通常表示你自己的远程仓库,也就是你 clone 下来的那个地址。
  • local 表示你电脑上的本地仓库。

2. Fork 之后,原仓库更新会自动同步吗?#

不会完全自动同步。 Fork 之后,你的 GitHub 仓库是原仓库在某一时刻的副本。 比如你在 6 月 1 日 fork 了项目:

original/project 6月1日版本
yourname/project 6月1日版本

后来原始仓库在 6 月 10 日更新了:

original/project 6月10日版本
yourname/project 仍然是6月1日版本

你的 fork 仓库不会自动变成最新状态。 GitHub 页面上有时候会显示:

This branch is 5 commits behind original:main

意思是你的 fork 落后于原仓库。 你可以在 GitHub 网页上点 Sync fork 来同步,也可以在本地用命令同步。


3. Fork 的更新是同步到 GitHub 里,还是同步到本地里?#

这要看你怎么操作。 如果你在 GitHub 网页上点 Sync fork,同步的是:

原始远程仓库 upstream → 你的远程仓库 origin

也就是说,GitHub 上你的 fork 更新了,但你本地电脑里的代码不会自动更新。

你还需要在本地执行:

Terminal window
git pull

把你远程仓库的新内容拉到本地。

如果你在本地用命令同步,一般流程是:

Terminal window
git remote add upstream https://github.com/original/project.git
git fetch upstream
git checkout main
git merge upstream/main 表示远程仓库 upstream 里的 main 分支
git push origin main

这套命令的含义是:

1. 添加原始仓库地址,命名为 upstream
2. 从 upstream 获取最新内容
3. 切换到本地 main 分支
4. 把 upstream/main 合并到本地 main
5. 把更新后的本地 main 推送到自己的 GitHub fork 仓库

这样本地和你的 GitHub fork 都会更新。


4. Clone 是什么?#

clone 是把远程仓库下载到本地。 比如:

Terminal window
git clone https://github.com/yourname/project.git

执行之后,本地会出现一个 project 文件夹。 这个文件夹不仅包含项目文件,还包含一个隐藏目录:

.git/

.git 里面保存了 Git 的版本信息、分支信息、提交历史、远程仓库地址等。 可以用下面的命令查看远程仓库地址:

Terminal window
git remote -v

一般你会看到:

Terminal window
origin https://github.com/yourname/project.git (fetch)
origin https://github.com/yourname/project.git (push)

这里的 origin 就是你自己的 fork 仓库。


5. Fork 和 Clone 的区别#

很多人会把 fork 和 clone 搞混。 它们的区别是:

fork:发生在 GitHub 上,是复制一个远程仓库到你的 GitHub 账号下。
clone:发生在本地电脑上,是把某个远程仓库下载到本地。

举个例子:

别人仓库:original/project
点击 Fork
你的仓库:yourname/project
执行 git clone
本地仓库:电脑里的 project 文件夹

所以 fork 和 clone 通常是配合使用的:

先 fork,再 clone。

6. Branch 分支是什么?#

分支可以理解成一条独立的开发线。

假设 main 分支是项目的主线:

main

你想开发一个新功能,不应该直接在 main 上乱改,而是新建一个分支:

Terminal window
git checkout -b feature-login

这表示:

从当前分支切出一个新分支,名字叫 feature-login,并切换过去。

现在你在 feature-login 分支上改代码,不会影响 main 分支。


7. 分支 A 和分支 B 的文件会互相影响吗?#

假设有两个分支:

分支 A:有 x、y、z、n 文件
分支 B:有 o、p、q、n 文件

这里 n 是公共文件。 如果你在分支 A 修改 n 文件:

A 分支的 n 被修改

此时不会影响 B 分支里的 n 文件。 因为每个分支都有自己的一套文件状态。 也就是说:

只要你还没有 merge,A 分支和 B 分支之间互不影响。

但是如果你后来把 A 合并到 B,或者把 B 合并到 A,就可能发生影响。


8. 如果 A 和 B 都修改了公共文件 n,会怎样?#

情况分两种。

情况一:修改的是 n 文件的不同位置#

比如:

A 分支修改了 n 文件第 10 行
B 分支修改了 n 文件第 50 行

这种情况下,Git 通常可以自动合并。

情况二:修改的是 n 文件的同一位置#

比如:

A 分支修改了 n 文件第 10 行
B 分支也修改了 n 文件第 10 行

这时 Git 不知道应该保留谁的修改,就会产生冲突。 冲突文件里通常会出现类似内容:

<<<<<<< HEAD
这是当前分支的内容
=======
这是要合并进来的分支的内容
>>>>>>> branch-name

你需要手动修改成最终想要的样子,然后执行:

Terminal window
git add n
git commit

这样冲突才算解决。


9. Merge 到底是合并到哪个分支?#

这是一个非常重要的问题。 Git 的 merge 规则是:

当前你在哪个分支,merge 就是把别的分支合并到当前分支。

比如现在有两个分支:

main
feature-login

如果你执行:

Terminal window
git checkout main
git merge feature-login

意思是:

把 feature-login 合并到 main。

如果你执行:

Terminal window
git checkout feature-login
git merge main

意思是:

把 main 合并到 feature-login。

所以 merge 的方向不是看命令里的分支是谁,而是看你当前所在的分支是谁。 记住一句话:

git merge xxx = 把 xxx 合并到我当前所在的分支。

10. 要不要单独搞一个分支作为主分支?#

通常不需要额外搞一个奇怪的“合并分支”。 一般项目结构是:

main:稳定主分支
dev:开发集成分支,可选
feature-xxx:具体功能分支
fix-xxx:修复 bug 分支

如果是个人小项目,通常这样就够了:

main
feature-xxx

开发流程:

Terminal window
git checkout main
git pull
git checkout -b feature-login
# 修改代码
git add .
git commit -m "add login feature"
git push origin feature-login

然后在 GitHub 上发 PR,把:

feature-login → main

合并进去。 如果是多人协作,可能会有:

main:正式稳定版本
dev:日常开发整合分支
feature-a:成员 A 的功能
feature-b:成员 B 的功能

流程可能是:

feature-a → dev
feature-b → dev
dev 测试稳定后 → main

但是对于大多数个人项目或者课程项目,不需要搞得太复杂。


11. Fork 之后,自己的远程仓库是不是 main 分支?#

一般是。 当你 fork 一个仓库时,你会复制原仓库的默认分支。 如果原仓库默认分支叫:

main

你的 fork 仓库默认分支通常也叫:

main

如果原仓库默认分支叫:

master

你的 fork 仓库默认分支通常也叫:

master

所以 fork 之后,你自己的远程仓库不一定必须是 main,要看原仓库默认分支叫什么。 可以用下面命令查看本地分支:

Terminal window
git branch

查看本地和远程所有分支:

Terminal window
git branch -a

12. 自己要不要搞一个 self 分支?#

一般不建议叫 self 分支。 更推荐按照任务命名,比如:

feature-login
feature-user-page
fix-navbar-bug
docs-update-readme
experiment-model-v2

如果你是 fork 了别人的仓库,想长期保留自己的修改版本,可以有一个自己的长期分支,比如:

my-main
custom
personal

但普通协作里,更推荐:

main:和原仓库主分支保持同步
feature-xxx:自己真正开发的内容

这样更清楚。 推荐结构:

upstream/main:原始仓库主分支
origin/main:你的 fork 仓库主分支,尽量和 upstream/main 保持同步
origin/feature-xxx:你自己的开发分支
local feature-xxx:你本地的开发分支

不要长期直接在自己的 main 上乱改,否则以后同步 upstream/main 的时候容易冲突。

简单来说就是自己新建一个自己的开发分支,然后你就在自己的开发分支里改东西即可,然后源仓库有修改的话直接合并到main分支,然后再把main分支里的东西合并到你自己的开发分支


13. Fork 项目的推荐工作流#

假设你 fork 了一个开源项目。

第一步:Fork#

在 GitHub 页面点击 Fork。 得到:

github.com/yourname/project

第二步:Clone 自己的 fork#

Terminal window
git clone https://github.com/yourname/project.git
cd project

第三步:添加原始仓库 upstream#

Terminal window
git remote add upstream https://github.com/original/project.git

查看远程地址:

Terminal window
git remote -v

应该看到:

origin https://github.com/yourname/project.git
upstream https://github.com/original/project.git

第四步:保持 main 干净#

Terminal window
git checkout main
git fetch upstream
git merge upstream/main
git push origin main

这一步的作用是让自己的 main 和原始仓库 main 保持一致。

第五步:从 main 新建功能分支#

Terminal window
git checkout -b feature-login

然后开始修改代码。

第六步:提交修改#

Terminal window
git status
git add .
git commit -m "add login feature"

第七步:推送到自己的 fork 仓库#

Terminal window
git push origin feature-login

第八步:发起 Pull Request#

在 GitHub 页面上创建 PR:

yourname/project:feature-login
→ original/project:main

意思是:

请求把你 fork 仓库里的 feature-login 分支合并到原始仓库的 main 分支。

14. 合并 Pull Request 是合并到哪里?#

PR 合并到哪里,取决于 PR 页面里选择的目标分支。

比如:

base repository: original/project
base branch: main
compare repository: yourname/project
compare branch: feature-login

这表示:

把 yourname/project 的 feature-login 合并到 original/project 的 main。

如果是你自己的项目,也可以是:

base repository: yourname/project
base branch: main
compare branch: feature-login

这表示:

把自己的 feature-login 合并到自己的 main。

所以 PR 的方向一定要看清楚:

compare → base

也就是:

你的修改分支 → 目标分支

15. 常见命令总结#

查看当前状态#

Terminal window
git status

查看当前分支#

Terminal window
git branch

查看所有分支,包括远程分支#

Terminal window
git branch -a

新建并切换分支#

Terminal window
git checkout -b feature-name

或者新版本 Git 可以用:

Terminal window
git switch -c feature-name

切换分支#

Terminal window
git checkout main

或者:

Terminal window
git switch main

查看远程仓库#

Terminal window
git remote -v

添加 upstream#

Terminal window
git remote add upstream https://github.com/original/project.git

从远程获取更新,但不自动合并#

Terminal window
git fetch origin
git fetch upstream

拉取并合并远程更新#

Terminal window
git pull origin main

等价于:

Terminal window
git fetch origin
git merge origin/main

合并分支#

Terminal window
git checkout main
git merge feature-name

意思是:

把 feature-name 合并到 main。

推送分支到远程#

Terminal window
git push origin feature-name

删除本地分支#

Terminal window
git branch -d feature-name

如果没有合并但强制删除:

Terminal window
git branch -D feature-name

删除远程分支#

Terminal window
git push origin --delete feature-name

16. fetch、pull、merge 的区别#

fetch#

Terminal window
git fetch upstream

意思是:

把远程仓库的新提交拿到本地,但不修改当前代码。

fetch 是比较安全的,因为它只是“下载更新信息”,不会直接动你的工作区。

merge#

Terminal window
git merge upstream/main

意思是:

把 upstream/main 合并到当前分支。

pull#

Terminal window
git pull upstream main

大致等于:

Terminal window
git fetch upstream
git merge upstream/main

所以 pull 是 fetch + merge。

新手建议多用:

Terminal window
git fetch
git merge

这样你更清楚发生了什么。


17. rebase 是什么?和 merge 有什么区别?#

merge 是把两个分支合并起来,会保留分叉历史。

例如:

main: A---B---C
feature: \---D---E

执行 merge 后可能变成:

main: A---B---C-------M
\ /
feature: D---E----

M 是一个 merge commit。

rebase 是把你的提交“搬到”最新主分支后面。

main: A---B---C
feature: \---D---E

执行 rebase 后变成:

main: A---B---C
feature: \---D'---E'

rebase 的历史更直,但对新手来说更容易出问题。

简单建议:

个人功能分支可以 rebase。
公共分支不要随便 rebase。
新手先用 merge。

18. 一个很常见的场景:原仓库更新了,我的分支怎么办?#

你正在 feature-login 分支开发,但原仓库 main 更新了。

推荐流程:

Terminal window
git checkout main
git fetch upstream
git merge upstream/main
git push origin main

这一步先更新自己的 main。

然后切回自己的功能分支:

Terminal window
git checkout feature-login
git merge main

意思是:

把最新 main 合并到自己的 feature-login。

这样你的功能分支就基于最新代码继续开发。

也可以用 rebase:

Terminal window
git checkout feature-login
git rebase main

但新手可以先用 merge。


19. 最容易搞混的几个问题#

问题 1:fork 后原仓库更新会同步到我的 fork 吗?#

不会自动同步。你需要手动 Sync fork,或者用命令 fetch upstream 再 merge。

问题 2:GitHub 上同步了 fork,本地会自动更新吗?#

不会。本地还需要 git pull。

问题 3:我在 A 分支改文件,会影响 B 分支吗?#

不会。只要没有 merge,两个分支互不影响。

问题 4:两个分支都改了同一个公共文件,会怎样?#

如果改的是不同位置,通常可以自动合并;如果改的是同一位置,可能出现冲突,需要手动解决。

问题 5:merge 是合并到哪个分支?#

合并到你当前所在的分支。

Terminal window
git checkout main
git merge feature-a

表示把 feature-a 合并到 main。

问题 6:fork 后我应该直接在 main 上改吗?#

不推荐。更好的方式是:

main 保持和原仓库同步
feature-xxx 用来写自己的修改

问题 7:要不要创建 self 分支?#

一般不需要。更推荐创建具体任务分支,比如 feature-login、fix-bug、docs-update。


20. 推荐的安全习惯#

习惯一:动手前先看状态#

Terminal window
git status
git branch

确认自己在哪个分支,当前有没有未提交修改。

习惯二:不要直接在 main 上开发#

推荐:

Terminal window
git checkout main
git pull
git checkout -b feature-xxx

习惯三:每个功能一个分支#

不要一个分支里同时改登录、首页、数据库、样式、文档。

更好的方式是:

feature-login
feature-homepage
fix-database-config
docs-readme

习惯四:提交信息写清楚#

不要总是:

Terminal window
git commit -m "update"

更好的写法:

Terminal window
git commit -m "fix navbar layout on mobile"
git commit -m "add user login form"
git commit -m "update README installation steps"

习惯五:PR 前先同步主分支#

Terminal window
git checkout main
git fetch upstream
git merge upstream/main
git push origin main
git checkout feature-xxx
git merge main
git push origin feature-xxx

这样可以减少 PR 冲突。


21. 一张图理解完整流程#

原始仓库 upstream
github.com/original/project
│ Fork
你的远程仓库 origin
github.com/yourname/project
│ Clone
你的本地仓库 local
电脑里的 project 文件夹

开发时:

upstream/main
│ 同步
origin/main
│ clone / pull
local/main
│ checkout -b
local/feature-xxx
│ push
origin/feature-xxx
│ Pull Request
upstream/main

22. 最推荐的新手工作流#

如果你 fork 了别人的项目,推荐这样做:

Terminal window
# 1. 克隆自己的 fork
git clone https://github.com/yourname/project.git
cd project
# 2. 添加原始仓库
git remote add upstream https://github.com/original/project.git
# 3. 更新自己的 main
git checkout main
git fetch upstream
git merge upstream/main
git push origin main
# 4. 新建功能分支
git checkout -b feature-my-change
# 5. 修改代码后提交
git add .
git commit -m "add my change"
# 6. 推送到自己的 fork
git push origin feature-my-change

然后在 GitHub 上发 PR:

yourname/project:feature-my-change
→ original/project:main

如果只是自己的项目,不涉及 fork,可以简化成:

Terminal window
git checkout main
git pull
git checkout -b feature-my-change
git add .
git commit -m "add my change"
git push origin feature-my-change

然后在 GitHub 上把 feature-my-change 合并到 main。


23. 最核心的一句话总结#

Fork 是复制别人的远程仓库,clone 是下载仓库到本地,branch 是在同一个仓库里开新的开发线,merge 是把一个分支合并到当前分支,PR 是在 GitHub 上请求把一个分支合并到另一个分支。

真正推荐的方式是:

main 保持干净和同步;
每个功能单独开分支;
开发完成后通过 PR 合并;
合并前先同步最新 main;
出现冲突就手动解决。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助

目录