☰
Git实战:从上传文件到指定目录到分支合并与冲突解决
2026/10/1 3:13:43 网站建设 项目流程

做开发这些年,我见过太多人栽在同一个地方:代码明明写好了,想把文件传到 GitHub 的指定目录,结果要么传到仓库根目录,要么把临时文件一股脑推了上去;做分支合并时,又在 merge 和 rebase 之间反复横跳,冲突一多直接原地蒙圈。其实把这些场景拆开看,它就是一套固定动作:本地把文件组织好,用 git add 和 git commit 打上快照,再按分支规则把提交推到 GitHub 对应路径,最后把分支合并回目标分支。这篇文章就是来把这条完整链路讲透的,覆盖 Git 安装配置、上传到指定文件夹、分支合并、冲突解决,以及我真实遇到过的报错和排查过程。适合刚接触 Git 的开发者,也适合已经会用基础命令、但对分支始终没把握的人。

1. 把“上传文件”和“分支合并”看成一个连续动作

1.1 指定文件夹在 Git 里到底是什么

“上传文件到 GitHub 的指定文件夹”这句话,特别容易让人产生网盘的联想,以为选中一个文件,扔到某个远程目录就完事了。实际在 Git 工作流里,根本没有“远程文件夹”这个独立概念,只有“仓库根目录下的相对路径”。

GitHub 仓库从根目录开始就是一棵文件夹树,你在网页上看到的 docs/notes/readme.md,本质上是本地仓库里 docs/notes/ 这个相对路径下的一份文件,在 push 之后被远程展示了出来。所以“上传到指定文件夹”的真正含义是:确保本地路径正确,让文件进入暂存区,提交到本地版本库,再推送远程分支。远程目录结构不会凭空出现,它完全取决于你本地仓库的目录结构。

很多人会在这一步犯一个基础错误:以为只要用 Git 命令指定一个远程路径,就能把一个本地文件直接放进任意目录。其实 Git 从未提供这种“魔法”命令。正确做法永远是把文件先放到本地仓库对应目录,再 add、commit、push。理解了这一层,后面就不会再纠结“为什么我 push 之后文件不在想放的文件夹里”了。

1.2 为什么推荐用 Git 命令而不是网页端拖拽

网页端其实支持直接上传文件,甚至支持拖拽。但这种方式有两个明显问题:一是不适合批量操作,几十个文件还要逐个定位目录;二是没有经过本地校验,缺少 diff 检查和 commit 记录控制,很容易把不该传的东西传上去。

更重要的是,网页上传无法解决“分支合并”这个后续动作。你写代码总不可能永远是直线发展,今天在 main 上改一点,明天在 feature 分支上改一点,最终都要走向合并。合并发生在 Git 的对象体系里,而不是文件夹层面。用本地命令流,每一笔变更都有据可查,合并时也能清楚看到两个分支各自做了什么修改。

我个人的习惯是:把网页端上传当成应急通道,比如临时补一份说明文档、改一下 README 错别字;凡是涉及正经开发内容的文件,一律通过本地 Git 流程走。这样既保证历史记录完整,也方便在合并之前做 review。

1.3 一条完整工作流包含哪些动作

可以把“上传文件”和“分支合并”放进同一个流水线里看待。举例来说,你在 feature/docs 分支上修改了 docs/guide.md,先 add、commit,把这个提交推到远程的 feature/docs 分支;然后切回 main,把 feature/docs 合并进来;最后 push main。这一步里,push 和 merge 是配合出现的:push 负责把本地提交同步到远端,merge 负责把不同分支的历史整合成一条完整主线。

很多新手的混乱点在于,分不清“推送到某个分支”和“合并到某个分支”的区别。假设你本地在 feature/log 分支,直接执行 git push origin main,如果 main 没有新的远程提交,Git 会尝试用当前 feature/log 的历史去快进更新 main;如果两边分叉,就可能被拒绝,或者需要强力覆盖——无论哪种,都不会产生“像 merge 那样干净的合并记录”。所以更安全的方式是:先推自己的分支,再通过 merge 或 rebase 把改动合进目标分支,最后推目标分支。先文件后合并,合并完再推送,这条顺序应该成为肌肉记忆。

2. 环境准备:装好 Git、配好身份、连通远程仓库

2.1 Windows 下安装 Git 的完整流程与坑点

如果你在 Windows 上开发,直接搜索“git for windows”,下载安装包后一路 Next 就可以。但有两个选项值得留意:一是安装完成后,建议把“Git Bash Here”和“Git GUI Here”的右键菜单打开,后面在任意目录里打开 Git Bash 会非常方便;二是默认编辑器如果没设过,可以保留 Vim,也可以用 VS Code,看个人使用习惯,我在第一次配置时就把默认编辑器设成了 VS Code,避免后来 commit 时误入 Vim 出不来的尴尬。

安装完不要忘记验证。打开终端或者 Git Bash,执行 git --version,能看到类似 git version 2.23.0.windows.1 这样的输出就说明安装成功。这里有个小坑:如果是刚装完,之前的终端窗口可能还没加载新环境变量,要重新打开一个终端窗口再执行。我遇到过好几次“明明装好了却提示不是内部或外部命令”,就是没重开终端。

还有个容易被忽略的问题:安装时如果选择了“调整 PATH 环境变量”选项,Git 会把它的 bin 目录写进系统 PATH。旧版本偶尔会出现和已有的开发工具链冲突的情况,所以安装完成后顺手执行 where git 看一下当前到底用的是哪个 git,能少踩很多环境坑。

2.2 第一次使用必须配置的两项身份信息

Git 提交记录里会记录“谁改的”,靠的就是 user.name 和 user.email。不配置的话,Git 可能会用系统默认用户名,提交记录看起来就是一串莫名其妙的机器名,协作时根本对不上人。配置方法很简单:

git config --global user.name "你的名字" git config --global user.email "你的邮箱"

这里的邮箱建议直接用 GitHub 账号里绑定过的邮箱,这样提交记录的头像和账号信息才能关联上。如果想对某个仓库单独配置,把 --global 去掉,在该仓库目录下执行即可。

除了身份信息,还有两个建议顺手做掉:

git config --global init.defaultBranch main git config --global pull.rebase false

第一行让新仓库默认分支叫 main,避免本地建仓库时默认 master、远程又是 main,两边对不上;第二行让 pull 默认使用 merge 策略,比较符合多数开发者的直觉。至于为什么这么说,后面讲合并策略时会细讲。

2.3 SSH 密钥和 HTTPS 凭证,二选一怎么选

连 GitHub 有两种主流方式:HTTPS 和 SSH。HTTPS 对新手更友好,clone 地址形如 https://github.com/user/repo.git,push 时输入用户名和访问令牌(Token)即可。现在 GitHub 已经不支持用账号密码直接 push,必须用 Personal Access Token,这一点很多人还不清楚,老报“Password authentication has been disabled”。

SSH 方式更省心,只需要把本地生成的公钥放到 GitHub 账号里。生成密钥:

ssh-keygen -t ed25519 -C "你的邮箱"

一路回车之后,默认会在用户目录下生成 id_ed25519 和 id_ed25519.pub 两个文件。用编辑器打开 .pub 文件,复制全部内容,到 GitHub 的 Settings -> SSH and GPG keys 里新增即可。验证是否连得上:

ssh -T git@github.com

看到 “Hi username! You've successfully authenticated” 就说明 SSH 打通了。我个人更推荐 SSH,尤其是需要长期维护的项目,一次性配置好后就不再需要反复输入 Token。不管用哪种方式,都要记得检查远程地址本身:

git remote -v

如果显示的是 https:// 开头,说明走了 HTTPS;如果显示 git@github.com:user/repo.git,说明走了 SSH。远程地址不对,后面所有 push 都会跟着错。

3. 实操步骤:把文件放进 GitHub 的指定文件夹并推上去

3.1 场景一:已有远程仓库,本地从空目录开始

这是最常见的场景:GitHub 上已经有一个仓库,你想在 docs/notes/ 这个目录下新增一份笔记文件,本地还没有这个仓库的副本。推荐先克隆整个仓库,而不是在本地 init 一个不相关的目录。

git clone git@github.com:user/repo.git cd repo mkdir -p docs/notes cp ~/Desktop/note.md docs/notes/ git status git add docs/notes/note.md git commit -m "docs: add note" git push origin main

一步步看:clone 会把远程仓库完整拉到当前目录,相当于把远程目录树整体复制到本地。mkdir -p 是确保路径存在,-p 的意思是“没有就创建,有就不报错”。cp 是把文件放进去,这一步决定了你实际要上传的“指定文件夹”。

git status 是为了看变更清单。此时 note.md 会以 Untracked 状态出现,add 指定路径后,它就进入暂存区。commit 是打个本地快照,push 则是把这个快照同步到远程的 main 分支。

这里有个很多人容易忽略的点:如果你在仓库里新建了一个空文件夹,Git 并不会跟踪它,GitHub 上也看不到这个空目录。因为 Git 跟踪的是文件,不是文件夹。非要保留空目录,就在里面放一个内容为空的 .gitkeep 文件,这是一种通用惯例,很多开源项目都在用。

3.2 场景二:本地项目是全新的,要整体建档上线

另一种场景是本地已经写好了一个项目,GitHub 上还没有仓库,或者只有一个空仓库。此时不需要先 clone 再重新摆放文件,直接在项目根目录初始化:

git init git branch -M main git add . git commit -m "init project" git remote add origin git@github.com:user/repo.git git push -u origin main

git init 会在当前目录生成 .git,让这里成为 Git 仓库。git branch -M main 是把分支名强制改成 main,和 GitHub 默认分支保持一致。git add . 是把当前目录所有未忽略文件加入暂存区,这一步风险最大,很容易把临时文件、编译产物、密钥文件一股脑加进去,所以 .gitignore 必须提前写好。

git remote add origin 是把本地仓库和远程仓库关联起来。最后 push 时的 -u 参数很关键,它会建立本地 main 分支和远程 main 分支的跟踪关系,后续直接执行 git pull 或 git push,就不用再写完整参数了。

如果你只想要指定文件夹,不想把整个项目根目录都推上去,那就在 git add 时给具体路径,例如 git add docs/,或者用 git add docs/guide.md。Git 允许只提交部分内容,这在只需要更新某个子目录的场景下非常管用。

3.3 场景三:单文件小改动,用网页端应急

如果只是简单补一个文件,比如 README 里的一张样例图,或者一个配置文件,直接用 GitHub 网页端的 Add file 按钮,也能实现“上传到指定文件夹”:先进入对应目录,再点 Add file -> Upload files,或者创建新文件时路径栏里直接写文件夹名/文件名,GitHub 会自动按路径创建目录。

这种方式胜在快,不用走完整本地流程。缺点也很明显:批量文件不方便,历史记录只有一条 web commit,很多规范公司不允许直接用网页改代码。我的建议是,网页端只用来处理文档、素材、配置文件;真正的源码、需要检测的脚本,走本地 Git 流程。

三种场景对比如下,方便按情况选:

场景推荐方式原因
已有仓库,新增指定目录文件本地 clone 后 git add保留完整历史,可本地校验
本地新项目上线本地 init 后关联远程目录结构原样映射,批量处理可控
单文件小改动网页端极速处理免安装、免克隆,文档类可接受

3.4 大文件和敏感文件怎么处理

GitHub 对单个文件有 100MB 的硬限制,建议超过 50MB 的文件就不要直接塞进仓库了。大文件要用 Git LFS(Large File Storage),它把大文件本体放到单独存储,仓库里只保留一个指针文件,需要时再拉取真实内容。安装 LFS 后先执行 git lfs install,然后对指定格式做跟踪:

git lfs track "*.zip" git add .gitattributes git commit -m "chore: track zip files with lfs"

至于敏感文件,比大文件更危险。比如 .env、密钥、数据库导出文件,一旦进过 Git 历史,即使后来删除也会残留在历史提交里。最好的处理方式是压根不让它进仓库,在 .gitignore 里写清楚:

.env *.pem node_modules/ dist/

一个实用技巧:执行 git add . 之前,先看一眼 git status 的输出,确认被追踪的文件列表里没有不该出现的文件。养成这个习惯,能避免九成以上的“误传密钥”事故。

4. 分支合并:从创建分支到落地合并,完整走一遍

4.1 分支不是复制文件,而是移动指针

Git 里的分支本质上是一个可移动的提交指针。创建分支不是复制代码,而是给当前提交打一个新的标签,未来在这个分支上提交时,指针会跟着新提交前进。理解这一点,就能明白“合并分支”其实是在整合提交历史,而不是比较两个文件夹谁新谁旧。

创建和切换分支的标准命令:

git switch -c feature/add-log

这条命令等于 git branch feature/add-log 加 git switch feature/add-log,一步到位。更早版本的 Git 用 git checkout -b 也能达到同样效果,两种写法我都用过,现在更推荐 switch,语义更清晰,不容易误操作。

如果你是要基于远程分支开发,比如远程有个 feature/one 分支,想拉到本地接着改:

git switch -c feature/one origin/feature/one

这样本地分支就自动关联了远程的 feature/one,后续 push 时可以少打参数。

4.2 用 merge 完成分支合并:三种结果一次讲清

merge 就是把另一个分支的历史整合进当前分支。具体会出现三种结果,取决于两个分支是否有分叉:

第一种是 fast-forward 快进合并。当前分支没有任何新提交,另一个分支领先了一段提交,此时 Git 只需要直接把当前分支指针往前移动,不会产生额外的合并提交,历史是一条直线。举例:main 的提交是 A,从 A 拉出 feature 分支后提交了 B 和 C,此时 main 还停在 A,那么切回 main 执行 git merge feature,结果就是把 main 从 A 直接移动到 C,速度最快且没有合并痕迹。

第二种是 --no-ff 合并,也就是强制生成一个合并提交。即便可以 fast-forward,仍然想让历史记录明确标注“从这里合并了 feature 分支”,就可以用:

git switch main git merge --no-ff feature/add-log

这样会生成一个新的 merge commit,提交信息默认是 Merge branch 'feature/add-log'。很多技术团队喜欢这种模式,因为可以从提交图上清楚看到每次合并的边界,方便回溯紧急改动。

第三种是真正的三方合并。两个分支都有各自的新提交,历史出现分叉,Git 会对比两个分支从共同祖先以来的所有改动,然后生成一个合并提交。如果两边改的不是同一个文件,或者改的是同一个文件的不同位置,Git 能自动合并成功;如果改了同一个文件的同一处,就会产生冲突,需要手动处理。

一个常见困惑是“为什么我 merge 之后没有生成 Merge commit”。原因很简单:Git 判断可以 fast-forward,就没必要多此一举。想要强制看到合并提交,就加 --no-ff。用表格总结:

合并结果触发条件是否产生 merge commit提交历史
fast-forward目标分支没有新提交否直线型
--no-ff主动要求保留合并节点是出现分支节点
三方合并两个分支都有分叉提交是有明显分叉汇聚

4.3 rebase 合并是不是更好的方式

除了 merge,还有一种整合分支的常见方式叫 rebase。它的思路是把当前分支的提交重新“嫁接”到目标分支的最新提交之后,让提交历史变成一条直线。

git switch feature/add-log git rebase main

执行完以后,feature 分支的提交会被重新应用到 main 的最新提交之后。如果你的代码有冲突,会在每个提交重放时依次处理,而不是像 merge 那样最后统一处理一次。rebase 的好处是历史干净,不会出现一堆 Merge branch 节点;坏处是它会改写提交顺序和哈希值,一旦分支已经被推送到远程,再 rebase 就需要强推,而强推会覆盖别人的提交,协作场景下非常危险。

所以我的经验是:对于还没推送到远程的本地分支,可以放心用 rebase 整理提交;对于已经和同事共享的分支,用 merge 更安全。判断标准就一句话——这段历史有没有被别人拉走过,有就 merge,没有才 rebase。

在实际项目里,我常用的组合拳是:在 feature 分支开发,提交若干次,推送到远程,创建 Pull Request,等 review 通过后直接在远端 Merge。本地不反复 rebase,避免给协作者制造信息差。

4.4 冲突解决:不要怕,按这个顺序处理

冲突是合并中最让人紧张的环节,但它的本质只是 Git 不知道怎么替你决定保留哪一版。这时 Git 会在冲突文件里插入冲突标记:

<<<<<<< HEAD 这里是当前分支的代码 ======= 这里是另一个分支的代码 >>>>>>> feature/add-log

处理步骤很简单。第一步,先看 git status,找到标记为 both modified 或 unmerged 的文件;第二步,用编辑器打开文件,逐个确认冲突段,保留正确内容,删掉冲突标记;第三步,把处理完的文件重新加入暂存区;第四步,直接 commit 完成合并。

git status # 编辑冲突文件 git add docs/guide.md git commit -m "merge: resolve conflict in docs/guide.md"

如果中途发现操作错了,或者合并进来一堆自己看不懂的改动,可以随时退回合并前状态:

git merge --abort

这个命令非常救命。有一次我接手一个老项目,feature 分支里文件编码和主分支不一样,冲突标的到处都是,我第一反应就是 merge --abort,然后重新梳理了分支差异再合并,几分钟就搞定了。记住:解决冲突前,先把当前分支的干净提交保存下来,再用武器的心态去面对冲突。git 的冲突标记和编辑器提示都能帮你定位,真正有疑问的地方,往往也就那么几个小区域。

一个小建议:不要试图在合并中间临时改功能。合并只负责把两份改动整合到一起,如果冲突文件里出现了逻辑层面的大改动需求,应该先解决当前冲突、完成合并,再开新分支处理功能,否则会把合并历史变得一团糟。

4.5 在 IntelliJ IDEA 里合并分支怎么点

很多不熟悉命令行的同学,习惯在 IntelliJ IDEA 里操作 Git。IDEA 的图形化功能其实已经封装得很好,而且大厂团队很多都用它。合并分支的路径是:右下角或者顶部 VCS 菜单里找到 Git -> Branches,弹出所有本地和远程分支列表;选择需要合并进来的分支,点 Merge into Current,IDEA 会自动执行 merge 逻辑。

如果出现冲突,IDEA 会弹出冲突对话框,左侧是本地版本,右侧是远端版本,中间是合并结果。你可以逐行选择保留哪边,也可以手动编辑中间区域。处理完后点击 Apply,IDEA 会帮你把文件标记为已解决,最后 Commit 并 Push。IDEA 里也有 Abort 按钮,作用等同于 git merge --abort。

我个人的看法是,IDEA 的合并可视化更适合新手,尤其是冲突标记不直观的时候,三栏对照比纯命令行友好得多。但命令行的好处是通用:不管你在哪台机器、哪个 IDE,只要装了 Git 就能操作,不会被具体工具绑死。两条路都值得掌握。

5. 高频错误实录:从报错信息到处理办法

5.1 fatal: not a git repository (or any of the parent directories): .git

这个报错非常经典,字面意思就是当前目录不是 Git 仓库,或者 Git 在向父目录逐级查找时也没有找到 .git 文件夹。常见原因有两种:一是你真的在某个子目录里执行了 git status,而这个子目录不属于任何已初始化的仓库;二是仓库根目录的 .git 文件夹被误删了,或是 clone 只复制了文件内容没有把隐藏文件带上。

排查方法很简单:逐步向上一级目录执行 git status,找到哪一层开始能识别为仓库。如果你的项目根目录确实没有 .git,但文件内容都在,说明当初拉取时没拉全,或者这个目录从未被初始化。此时可以回到项目根目录执行 git init,再关联远程地址。

另一种隐蔽情况是:在仓库里又执行了 git init,把整个仓库嵌套进了另一个仓库。此时外层仓库会把内层目录当成一个普通的子目录或子模块,提交时根本不会追踪内层仓库内部的文件,很容易出现“明明 add 了,但远程看不到”的诡异问题。我的处理方法是:在一个项目目录里先坚定地确认谁是根仓库,不要随意多重 init。

5.2 SSH 认证失败 / Permission denied(publickey)

执行 git push 时经常遇到类似这样的一行:

git@github.com: Permission denied (publickey).

意思是 SSH 方式下,GitHub 不认你当前的本机密钥。先按顺序排查:一是密钥文件是否存在,执行 ls ~/.ssh/id_ed25519.pub,如果不存在,说明密钥没生成或者路径不对;二是密钥是否已添加到 GitHub,浏览器登录 GitHub,在 Settings -> SSH keys 里查看有没有对应公钥;三是本机 ssh-agent 是否加载了密钥:

ssh-add ~/.ssh/id_ed25519

四是远端地址是不是用了 SSH。如果远端地址是 https:// 开头,你推送时走的是 HTTPS 认证,跟 SSH 密钥无关,会报别的错误。改地址可以用:

git remote set-url origin git@github.com:user/repo.git

我遇到过最迷惑的一次是,VSCode 里能正常 pull,但命令行 push 一直报 Permission denied。最后发现终端里当前用户和 VSCode 启动用户不一致,ssh-agent 加载的密钥不是同一个。简单来说,SSH 认证失败先自己按上面几步排除,完全够用。

5.3 git commit --amend 怎么用才安全

这个命令是用来修正“最后一次提交”的。典型场景是:提交完才发现漏了一个文件,或者 commit message 写错了。用法是先把遗漏文件加进暂存区,再执行:

git add 漏掉的文件 git commit --amend -m "新的提交信息"

amend 的作用是把你当前暂存区里的内容合并进上一次 commit,并生成一个新的提交哈希。也就是说,上一次提交被改写成了另一次提交,而不是新增一次“补充提交”。这非常适合本地分支上的提交整理,能让提交历史更干净。

但这个命令有一个前提:上一次提交还没有被推到远程共享。如果已经 push 到 GitHub,被别人 clone 过,那 amend 就会产生分叉历史,后面对齐很麻烦。强行覆盖远程需要 git push --force-with-lease,这个操作只应该在确认不会影响协作时使用。我的习惯是:push 之前完成所有 amend 整理,一旦 push 出去,就只用新的 commit 来修正,不再改写历史。

使用 amend 时也要注意,它不只是改信息,是连提交内容一起替换。如果你只想改 message,什么都没 add,也可以直接执行 git commit --amend -m "new message"。它不会删除工作区的修改,只调整上次 commit 的快照。

5.4 把 push 被拒绝:non-fast-forward 怎么办

这个错误在多人协作时太常见了。你本地改了代码准备 push,结果远程分支已经有别人先推了新的提交,历史分叉,Git 会拒绝你的 push,提示 Updates were rejected because the remote contains work that you do not have locally。

正确做法不是强推,而是先把远程新提交拉到本地合并,再推送。常用两种方式:

git pull origin main git push origin main

git pull 默认会把远程分支 merge 到本地分支,相当于先合并再推送。如果你本地几乎没有新的提交,用 git pull --rebase 也可以保持直线历史。拉到最新后如果出现冲突,按第 4.4 节的处理方式解决,然后正常 push。

强推是最后手段。除非仓库只有你一个人,否则不要用 git push --force。因为强推相当于用本地历史覆盖远端历史,别人的提交会被直接丢弃。真需要覆盖时,用 --force-with-lease,它只有在你认为的远端状态和实际一致时才会执行,能降低一点风险。

5.5 GitHub 访问变慢或 push 超时了怎么办

从代码层面讲,Git 不会无故超时。常见的两种诱因,一是本机网络有问题,二是从本机到 GitHub 之间的网络线路在高峰期容易出现延迟和丢包。判断方法很简单:先用浏览器打开几个常用网站,如果都卡,问题在于本机网络;如果只有 GitHub 响应慢,那多半是跨地域线路的常见波动,换个时间段再试往往会恢复正常。

排查时可以执行:

git ls-remote git@github.com:user/repo.git

这个命令只会在远程探测分支引用,如果长时间不返回,说明本机和 GitHub 之间的连接不太健康。这时候不要反复重试同一次 push,更不要自作聪明地改一堆配置,先做三件事:刷新 DNS 缓存(Windows 下执行 ipconfig /flushdns)、确认当前网络连接正常、过几分钟再试。如果该项目是你个人项目,也可以考虑把大文件提交拆小,分多次推送,减少单次传输的压力。

有段时间我的仓库偶尔会在 push 时卡顿,我一度以为是代码问题,后来发现是本地网络路由抖动。冷静下来等一等,问题自然就过了。如果企业内网还涉及额外限制,那就先确认 443 端口是否放行,这属于基础连通性检查,和代码无关。

5.6 Git LFS 相关报错和文件过大问题

GitHub 对仓库里单个文件超过 100MB 时会直接拒绝 push。如果你误传了一个大文件,最常见的报错是“this exceeds GitHub's file size limit”。处理分两步:先把该文件从当前跟踪列表中移除并提交,再把本地历史里的大文件清理掉。只是删除当前文件还不够,因为历史提交里还留着那个大文件,push 依然会被拒绝。

便捷的方式是安装 git filter-repo 进行历史重写,但对新手来说,最重要的是防患于未然。养成在项目初始化时就把大文件相关路径写进 .gitignore 的习惯,或者提前用 git lfs track 标记好大文件后缀。我在涉及游戏素材、测试数据的项目里,会在第一笔提交时就把.psd、.zip、*.mp4 全部交给 LFS 管理,后面基本没再为文件过大发过愁。

6. 给新手的工作流建议和我的几个私人习惯

6.1 每天开工和收工的固定动作

早上到工位,先不要在本地闷头改代码,先把远端状态同步下来:

git fetch --prune origin git pull origin main

fetch 不会改动本地工作区,只是把远端信息取回来;pull 会把 main 的新提交合到本地。--prune 会清理远端已经删除的分支的本地跟踪记录,避免分支列表越攒越乱。收工之前,不管代码改到哪一步,先看一下 git status,把有效改动提交,否则第二天很容易丢失上下文。

这一步看似简单,却能让工作节奏非常清晰。很多分支合并问题,本质都是本地长期不 pull,导致提交历史越分叉越远,最后一下冲突特别大。每天同步一次,能显著减少这种“历史鸿沟”。

6.2 提交节奏和提交信息怎么写

提交频率不要走极端:既不要三天一次大提交,也不要每改一行就提交。比较合理的节奏是:一个功能点完成后提交一次,文档改动单独提交,bug 修复单独提交。这样后续合并代码时,能够很容易找到某一次具体改了什么。

提交信息建议按约定格式写,比如:fix: 修复登录超时问题、feat: 增加导出功能、docs: 更新部署文档。好处是合并分支时扫一眼就能知道每个提交是干什么的。我们可以夸张一点地说,规范提交信息不是给 GitHub 看的,是给两周后的自己看的。很多次我回看旧项目,都是靠清晰提交信息才快速定位到改动位置的。

6.3 合并前的一点小仪式感

在把 feature 分支合并进 main 之前,我会强制自己多做一个动作:先在 feature 分支上执行一遍 git status,确认没有未提交的修改;然后把当前分支切到 main,执行 git pull 更新本地 main 到最新;最后再 merge。这一套不超过两分钟,但能避免“我以为我 merge 的是最新代码,其实本地 main 已经很旧”的尴尬。

另外,合并完成后先不要急着删 feature 分支,等 push 成功并在 GitHub 上确认无误后,再删远端分支也不迟。删除本地分支用:

git branch -d feature/add-log

如果分支没有合并,Git 会拒绝删除,这是保护机制。真要强行删除,才需要 -D。我很少用 -D,因为这通常意味着有提交会丢失。

踩过这么多次坑之后,我最深的体会是:Git 本身并不复杂,复杂的是人总想跳过中间步骤。上传文件到 GitHub 指定文件夹,看着像传输问题,本质是目录管理和提交记录问题;分支合并,看着像命令问题,本质是对历史分叉的理解问题。只要每次动手前先看一遍 git status,每次 push 前想清楚自己提交的是什么,这套流程会可靠很多。最后再分享一个小技巧:在本地仓库里永远保持 main 分支是能跑的版本,所有未完成的工作都在分支上进行;等合并时,再用第 4 节那套流程把功能安全地汇入主线。用不了多久,你就会发现这些操作已经不需要思考了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询