你真的会用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然后你在本地执行:
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 更新了,但你本地电脑里的代码不会自动更新。
你还需要在本地执行:
git pull把你远程仓库的新内容拉到本地。
如果你在本地用命令同步,一般流程是:
git remote add upstream https://github.com/original/project.gitgit fetch upstreamgit checkout maingit merge upstream/main 表示远程仓库 upstream 里的 main 分支git push origin main这套命令的含义是:
1. 添加原始仓库地址,命名为 upstream2. 从 upstream 获取最新内容3. 切换到本地 main 分支4. 把 upstream/main 合并到本地 main5. 把更新后的本地 main 推送到自己的 GitHub fork 仓库这样本地和你的 GitHub fork 都会更新。
4. Clone 是什么?
clone 是把远程仓库下载到本地。 比如:
git clone https://github.com/yourname/project.git执行之后,本地会出现一个 project 文件夹。 这个文件夹不仅包含项目文件,还包含一个隐藏目录:
.git/.git 里面保存了 Git 的版本信息、分支信息、提交历史、远程仓库地址等。
可以用下面的命令查看远程仓库地址:
git remote -v一般你会看到:
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 上乱改,而是新建一个分支:
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你需要手动修改成最终想要的样子,然后执行:
git add ngit commit这样冲突才算解决。
9. Merge 到底是合并到哪个分支?
这是一个非常重要的问题。 Git 的 merge 规则是:
当前你在哪个分支,merge 就是把别的分支合并到当前分支。比如现在有两个分支:
mainfeature-login如果你执行:
git checkout maingit merge feature-login意思是:
把 feature-login 合并到 main。如果你执行:
git checkout feature-logingit merge main意思是:
把 main 合并到 feature-login。所以 merge 的方向不是看命令里的分支是谁,而是看你当前所在的分支是谁。 记住一句话:
git merge xxx = 把 xxx 合并到我当前所在的分支。10. 要不要单独搞一个分支作为主分支?
通常不需要额外搞一个奇怪的“合并分支”。 一般项目结构是:
main:稳定主分支dev:开发集成分支,可选feature-xxx:具体功能分支fix-xxx:修复 bug 分支如果是个人小项目,通常这样就够了:
mainfeature-xxx开发流程:
git checkout maingit pullgit 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 → devfeature-b → devdev 测试稳定后 → main但是对于大多数个人项目或者课程项目,不需要搞得太复杂。
11. Fork 之后,自己的远程仓库是不是 main 分支?
一般是。 当你 fork 一个仓库时,你会复制原仓库的默认分支。 如果原仓库默认分支叫:
main你的 fork 仓库默认分支通常也叫:
main如果原仓库默认分支叫:
master你的 fork 仓库默认分支通常也叫:
master所以 fork 之后,你自己的远程仓库不一定必须是 main,要看原仓库默认分支叫什么。 可以用下面命令查看本地分支:
git branch查看本地和远程所有分支:
git branch -a12. 自己要不要搞一个 self 分支?
一般不建议叫 self 分支。 更推荐按照任务命名,比如:
feature-loginfeature-user-pagefix-navbar-bugdocs-update-readmeexperiment-model-v2如果你是 fork 了别人的仓库,想长期保留自己的修改版本,可以有一个自己的长期分支,比如:
my-maincustompersonal但普通协作里,更推荐:
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
git clone https://github.com/yourname/project.gitcd project第三步:添加原始仓库 upstream
git remote add upstream https://github.com/original/project.git查看远程地址:
git remote -v应该看到:
origin https://github.com/yourname/project.gitupstream https://github.com/original/project.git第四步:保持 main 干净
git checkout maingit fetch upstreamgit merge upstream/maingit push origin main这一步的作用是让自己的 main 和原始仓库 main 保持一致。
第五步:从 main 新建功能分支
git checkout -b feature-login然后开始修改代码。
第六步:提交修改
git statusgit add .git commit -m "add login feature"第七步:推送到自己的 fork 仓库
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/projectbase branch: main
compare repository: yourname/projectcompare branch: feature-login这表示:
把 yourname/project 的 feature-login 合并到 original/project 的 main。如果是你自己的项目,也可以是:
base repository: yourname/projectbase branch: main
compare branch: feature-login这表示:
把自己的 feature-login 合并到自己的 main。所以 PR 的方向一定要看清楚:
compare → base也就是:
你的修改分支 → 目标分支15. 常见命令总结
查看当前状态
git status查看当前分支
git branch查看所有分支,包括远程分支
git branch -a新建并切换分支
git checkout -b feature-name或者新版本 Git 可以用:
git switch -c feature-name切换分支
git checkout main或者:
git switch main查看远程仓库
git remote -v添加 upstream
git remote add upstream https://github.com/original/project.git从远程获取更新,但不自动合并
git fetch origingit fetch upstream拉取并合并远程更新
git pull origin main等价于:
git fetch origingit merge origin/main合并分支
git checkout maingit merge feature-name意思是:
把 feature-name 合并到 main。推送分支到远程
git push origin feature-name删除本地分支
git branch -d feature-name如果没有合并但强制删除:
git branch -D feature-name删除远程分支
git push origin --delete feature-name16. fetch、pull、merge 的区别
fetch
git fetch upstream意思是:
把远程仓库的新提交拿到本地,但不修改当前代码。fetch 是比较安全的,因为它只是“下载更新信息”,不会直接动你的工作区。
merge
git merge upstream/main意思是:
把 upstream/main 合并到当前分支。pull
git pull upstream main大致等于:
git fetch upstreamgit merge upstream/main所以 pull 是 fetch + merge。
新手建议多用:
git fetchgit merge这样你更清楚发生了什么。
17. rebase 是什么?和 merge 有什么区别?
merge 是把两个分支合并起来,会保留分叉历史。
例如:
main: A---B---Cfeature: \---D---E执行 merge 后可能变成:
main: A---B---C-------M \ /feature: D---E----M 是一个 merge commit。
rebase 是把你的提交“搬到”最新主分支后面。
main: A---B---Cfeature: \---D---E执行 rebase 后变成:
main: A---B---Cfeature: \---D'---E'rebase 的历史更直,但对新手来说更容易出问题。
简单建议:
个人功能分支可以 rebase。公共分支不要随便 rebase。新手先用 merge。18. 一个很常见的场景:原仓库更新了,我的分支怎么办?
你正在 feature-login 分支开发,但原仓库 main 更新了。
推荐流程:
git checkout maingit fetch upstreamgit merge upstream/maingit push origin main这一步先更新自己的 main。
然后切回自己的功能分支:
git checkout feature-logingit merge main意思是:
把最新 main 合并到自己的 feature-login。这样你的功能分支就基于最新代码继续开发。
也可以用 rebase:
git checkout feature-logingit rebase main但新手可以先用 merge。
19. 最容易搞混的几个问题
问题 1:fork 后原仓库更新会同步到我的 fork 吗?
不会自动同步。你需要手动 Sync fork,或者用命令 fetch upstream 再 merge。
问题 2:GitHub 上同步了 fork,本地会自动更新吗?
不会。本地还需要 git pull。
问题 3:我在 A 分支改文件,会影响 B 分支吗?
不会。只要没有 merge,两个分支互不影响。
问题 4:两个分支都改了同一个公共文件,会怎样?
如果改的是不同位置,通常可以自动合并;如果改的是同一位置,可能出现冲突,需要手动解决。
问题 5:merge 是合并到哪个分支?
合并到你当前所在的分支。
git checkout maingit merge feature-a表示把 feature-a 合并到 main。
问题 6:fork 后我应该直接在 main 上改吗?
不推荐。更好的方式是:
main 保持和原仓库同步feature-xxx 用来写自己的修改问题 7:要不要创建 self 分支?
一般不需要。更推荐创建具体任务分支,比如 feature-login、fix-bug、docs-update。
20. 推荐的安全习惯
习惯一:动手前先看状态
git statusgit branch确认自己在哪个分支,当前有没有未提交修改。
习惯二:不要直接在 main 上开发
推荐:
git checkout maingit pullgit checkout -b feature-xxx习惯三:每个功能一个分支
不要一个分支里同时改登录、首页、数据库、样式、文档。
更好的方式是:
feature-loginfeature-homepagefix-database-configdocs-readme习惯四:提交信息写清楚
不要总是:
git commit -m "update"更好的写法:
git commit -m "fix navbar layout on mobile"git commit -m "add user login form"git commit -m "update README installation steps"习惯五:PR 前先同步主分支
git checkout maingit fetch upstreamgit merge upstream/maingit push origin main
git checkout feature-xxxgit merge maingit push origin feature-xxx这样可以减少 PR 冲突。
21. 一张图理解完整流程
原始仓库 upstreamgithub.com/original/project │ │ Fork ▼你的远程仓库 origingithub.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/main22. 最推荐的新手工作流
如果你 fork 了别人的项目,推荐这样做:
# 1. 克隆自己的 forkgit clone https://github.com/yourname/project.gitcd project
# 2. 添加原始仓库git remote add upstream https://github.com/original/project.git
# 3. 更新自己的 maingit checkout maingit fetch upstreamgit merge upstream/maingit push origin main
# 4. 新建功能分支git checkout -b feature-my-change
# 5. 修改代码后提交git add .git commit -m "add my change"
# 6. 推送到自己的 forkgit push origin feature-my-change然后在 GitHub 上发 PR:
yourname/project:feature-my-change→ original/project:main如果只是自己的项目,不涉及 fork,可以简化成:
git checkout maingit pullgit checkout -b feature-my-changegit 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;出现冲突就手动解决。支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!