first-contributions 进阶指南:从修改提交到解决冲突的完整 Git 实战手册
2026/9/18 20:42:22 网站建设 项目流程

first-contributions 进阶指南:从修改提交到解决冲突的完整 Git 实战手册

【免费下载链接】first-contributions🚀✨ Help beginners to contribute to open source projects项目地址: https://gitcode.com/gh_mirrors/fi/first-contributions

导读

完成 first-contributions 主教程的首次 Pull Request 之后,你已经掌握了 fork、clone、branch、commit、push 与 PR 的基础闭环。但真实的开源协作远不止于此:提交信息写错了怎么办?Fork 落后于上游仓库怎么办?两个分支同时改了同一行代码怎么办?本篇文章以仓库 孟加拉语补充材料索引 为骨架,系统展开其引用的全部 13 个进阶 Git 主题,覆盖提交修正、历史重写、分支治理、冲突处理与凭据管理五大场景,让你在参与开源项目时不再畏惧任何一次"意外"。

前置说明:这份补充材料是什么

仓库中每一份补充文档都默认读者已经完成了 primary tutorial(fork 上游 → clone 到本地 → 新建<add-your-name>分支 → 提交 → 发起 Pull Request)。因此,下文涉及的所有操作都发生在真实开源协作的上下文里:你的仓库同时存在origin(自己的 GitHub Fork)与upstream(原项目公共仓库)两个远程,以及本地、Fork、上游三方协作的"三角工作流"。

原索引以 additional-material.be.md 收录了 10 篇 git_workflow_scenarios 下的操作文档,外加 .gitignore、凭据存储与实用链接共 13 个主题。下文逐一展开,每节都给出可直接复制的命令与关键注意点。

一、修改提交:git commit --amend

对应文档:amending-a-commit.md

场景一:提交推送到远程后发现提交信息有拼写错误,或发现自己漏改了一行。你不需要新建一个"补救提交",只需修改最近一次提交。

修改最近一次提交的信息

git commit --amend -m "新的提交信息" git push origin <branch-name>
  • 不加-m直接运行git commit --amend,Git 会打开默认文本编辑器,等你修改提交信息后保存退出;
  • 加上-m标志则跳过编辑器,直接以新信息替换原信息。

把漏改的内容并入上一次提交

假设你的提交历史如下:

g56123f create file botfile a2235d updated contributor.md a5da0d modified botfile

你发现a5da0d里漏写了一个单词。两种做法:一是新建一条独立提交;二是把新改动并入a5da0d,让改动保持"一个提交一个主题"。后一种对小型修正更干净,操作如下:

# 1. 修改文件(把遗漏的单词补上) # 2. 加入暂存区 git add <filename> # 3. 修改上一次提交(会打开编辑器,可保留或改写原信息) git commit --amend # 4. 推送 git push origin <branch-name>

修改已推送到远程的提交

一旦提交已经推送到远程,git commit --amend本质上是用一个新提交替换旧提交,本地历史将与远程历史分叉。要让远程也更新,必须强制推送覆盖远程分支历史:

git add <your changed files> git commit --amend -m "followed by your new commit message" git push --force

⚠️ 警告:git push --force会直接覆盖远程分支、丢弃远程上已有的改动——包括其他协作者在此期间推送的内容。 更安全的替代方案是git push --force-with-lease:推送前 Git 会先核对远程分支是否仍是你上次拉取时的状态,若是,则拒绝推送并提醒你,避免误伤他人的提交。在你无意覆盖别人改动时,应优先使用它。

二、配置 Git 身份与更多选项

对应文档:configuring-git.md

第一次运行git commit时,你可能会看到这样的提示:

$ git commit *** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity. Omit --global to set the identity only in this repository.

Git 要求每次提交都绑定名字与邮箱,这是协作的基础:只有这样才能知道"谁在什么时候改了什么"。向 Git 提供身份有三种作用域,优先级从高到低为:命令行级 > 仓库级 > 全局级。

全局配置(Global)

存入全局配置后,本机所有仓库都会生效,适用于大多数场景:

git config --global user.email "you@example.com" git config --global user.name "Your Name"

通用语法:git config --global <变量名> <值>

仓库配置(Repository)

省略--global,配置只作用于当前仓库。典型场景:工作项目用公司邮箱、个人项目用私人邮箱:

git config user.email "you@alternate.com" git config user.name "Your Name"

通用语法:git config <变量名> <值>

命令行配置(Command-line)

仅对单条命令生效。所有 Git 命令都支持在动作动词之前用-c传入临时配置:

git -c user.name='Your Name' -c user.email='you@example.com' commit -m "Your commit message"

通用语法:git -c <变量-1>=<值> -c <变量-2>=<值> <command>

优先级说明

三种方式的生效优先级是命令行级 > 仓库级 > 全局级。例如某个变量同时在命令行和全局配置中出现,本次操作使用命令行中的值。

身份之外的其他配置项

  • core.editor—— 指定编写提交信息等场景使用的编辑器名称;
  • commit.template—— 指定系统上一个文件作为初始提交信息模板;
  • color.ui—— 布尔值,控制 Git 输出是否使用颜色。

三、保持 Fork 与上游仓库同步

对应文档:keeping-your-fork-synced-with-this-repository.md

开源协作的典型结构是"三角工作流":上游公共仓库(upstream)→ 你的 GitHub Fork(origin)→ 本地仓库,一共三个仓库。Pull Request 只能从你的 Fork 发起,所以同步的次序是:先让本地与上游同步,再让本地推送到 Fork。GitHub 提示"你落后 N 个提交"时,就该执行下面的流程。

完整同步流程

# 1. 确认当前在 main 分支(git status 的第一行会显示当前分支) git status # 如果不在 main: git checkout main # 2. 添加上游远程(只需做一次),命名为 upstream git remote add upstream https://github.com/firstcontributions/first-contributions.git # 3. 拉取上游最新内容 git fetch upstream # 4. 把上游 main 变基/合并进本地 main git rebase upstream/main # 5. 推送到你的 GitHub Fork(origin) git push origin main

一步到位的快捷方式

如果只想一次性拉取并合并上游main到当前本地分支:

git pull upstream main

此后本地、Fork、上游三方保持一致。建议每次看到 GitHub 提示落后时都执行一遍同步,再做新功能开发,可大幅减少后续的合并冲突。

四、把提交移动到正确的分支

对应文档:moving-a-commit-to-a-different-branch.md

不小心在错误的分支上提交了代码?两条路线可以补救。

移动到已存在的分支

git reset HEAD~ --soft # 撤销最后一次提交,但保留文件改动 git stash # 记录当前工作目录状态 git checkout name-of-the-correct-branch # 切换到正确的分支 git stash pop # 恢复之前暂存的状态 git add . # 或逐个添加文件 git commit -m "your message here" # 在正确分支上重新提交

移动到新建的分支

git branch newbranch # 创建新分支,保留全部提交 git reset --hard HEAD~# # 当前分支回退 # 个提交(这些提交将从当前分支消失) git checkout newbranch # 切换到新分支,它拥有全部提交

⚠️ 注意:git reset --hard会丢弃未提交的改动。执行前确认没有未保存的工作。

五、从 Git 仓库移除文件

对应文档:removing-a-file.md

有时你想让 Git 停止跟踪某个文件,但文件本身还要留在电脑上(例如误提交的配置文件)。核心命令:

git rm <file> --cached

原理说明

加上--cached后,Git 不再跟踪该文件的变更,从版本控制角度看如同已删除,但文件仍然存在于磁盘上。如果不加--cached,Git 会同时把文件从仓库和你的文件系统中删除。

之后照常提交并推送,远程仓库就会移除该文件:

git commit -m "Remove file1.js" git push origin main

批量与通配符用法

# 一次移除多个文件 git rm file1.js file2.js file3.js --cached # 用通配符移除同类文件(例如所有 .txt) git rm *.txt --cached

六、删除本地与远程分支

对应文档:removing-branch-from-your-repository.md

按主教程做完贡献后,<add-your-name>分支已完成了它的使命,可以清理掉。先把它合并进main,再删除本地分支:

git checkout main git merge <add-your-name> main git branch -d <add-your-name>

删除远程分支(GitHub Fork 上的<add-your-name>)则需要谨慎:在维护者尚未合并你的 Pull Request 之前,千万不要删除它。只有确认 PR 已合并后,才执行:

git push origin --delete <add-your-name>

这样本地与远程的分支都保持整洁。时间一长上游仓库会积累大量新提交,记得回到第三节的同步流程保持三方一致。

七、解决合并冲突

对应文档:resolving-merge-conflicts.md

什么是合并冲突

当不同分支的改动相互冲突、Git 无法自动合并时就会产生冲突。常见场景:

  • 两个贡献者修改了同一文件的同一行;
  • 一个贡献者删除了另一个贡献者正在修改的文件;
  • 两个分支把同一文件重命名成了不同名字。

此时 Git 会暂停合并,把冲突文件标记出来等待人工处理。本教程聚焦命令行解法。

五步解决流程

1. 找出冲突文件。合并失败后运行:

git status

在 "Unmerged paths" 下查找冲突文件列表。

2. 打开冲突文件查看标记。Git 用冲突标记标出边界:

<<<<<<< HEAD 你的改动 ======= 传入的改动 >>>>>>> branch-name
  • <<<<<<< HEAD以下是当前分支的改动;
  • =======分隔双方改动;
  • >>>>>>> branch-name以下是另一分支传入的改动。

3. 手动解决冲突。三种选择:保留你的改动、接受传入的改动、或把两者有意义地合并。编辑完成后,务必删除<<<<<<<=======>>>>>>>这些冲突标记

4. 标记为已解决

git add <filename>

对每个冲突文件重复此步骤。

5. 提交合并

git commit -m "Resolved merge conflicts"

至此合并流程收尾。

辅助工具

# 启动可视化合并工具(需先安装 Meld、KDiff3、Beyond Compare 等) git mergetool # 想放弃本次合并时 git merge --abort

减少冲突的最佳实践

  • 经常从主分支拉取更新:git pull origin main
  • 每个功能/修复使用独立分支:git checkout -b feature-branch

八、还原提交:git revert

对应文档:reverting-a-commit.md

git revert相当于 Git 世界的 "Ctrl+Z":它新建一条提交来撤销另一条提交的所有改动,历史保持线性增长,非常适合已经推送到远程的提交。每个提交都有唯一的 SHA(Secure Hash Algorithm)标识,只要能拿到 SHA 就能还原它,但要注意按顺序还原以免搞乱仓库。

步骤

# 1. 查看提交历史(--oneline 以一行简洁形式显示,每行开头是 7 位短 SHA) git log --oneline

示例输出:

389004d added spacing in title c1b9fc1 Merge branch 'master' into tutorials 77eaafd added tutorial for reverting a commit
# 2. 复制目标提交的 SHA(如 389004d) git revert 389004d

Git 会打开文本编辑器让你编辑提交信息,可以保留默认以Revert开头的消息,也可以自定义。

# 3. 保存并关闭编辑器 # 4. 推送 git push origin <branch-name>

完成。本例中仓库将回到c1b9fc1时的状态。

九、压缩提交:git rebase -i

对应文档:squashing-commits.md

什么是 Squash

Squash 即重写提交历史,把多个提交合并成一个带有完整描述的提交。开源项目经常要求这样做:分支上大量的过程性提交只对作者本人有意义,合并成一个提交后,改动描述更清晰、日后也更容易整体还原。

操作步骤

先查看要合并的提交:

git log

会看到类似:

commit blablabla Author: omguhh Date: 10/10/20 Commit message 1 commit blablabla2 Author: omguhh Date: 10/10/20 Commit message 2

进入交互式 rebase,并指定回溯范围:

git rebase -i HEAD~2

编辑器会打开一个待办列表:

pick blablabla Changing test01.txt file pick blablabla2 Adding dummy01.txt file # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out

把第二条的pick改为squash,使其并入上一条:

pick blablabla Changing test01.txt file squash blablabla2 Adding dummy01.txt file

保存退出后,Git 会打开提交信息编辑器,展示两条提交信息的组合:

# This is a combination of 2 commits. # The first commit's message is: commit message 1 # This is the 2nd commit message: commit message 2

自由修改后保存退出。再次运行git log,两个提交已合并为一个。

十、撤销本地提交:git reset

对应文档:undoing-a-commit.md

git reset系列用于撤销尚未推送的本地提交。三种模式各有用途。

软撤销:仅重置暂存区

git reset

把暂存区重置到最近一次提交,工作目录的改动保留,可以重新提交。若只想把某个文件移出暂存区:

git reset <file>

经典用法——把误合在一起的改动拆成两条提交:

# 修改 index.php 和 tutorial.php # 全部加入暂存区 $ git add . # 想起两个文件需要分开提交 # 先把 tutorial.php 移出暂存区 $ git reset tutorial.php # 先提交 index.php $ git commit -m "Changed index.php" # 再提交 tutorial.php $ git add tutorial.php $ git commit -m "Changed tutorial.php"

硬重置:彻底回到上次提交

git reset --hard

不仅重置暂存区,还把工作目录的所有文件改动一并还原到上次提交。--hard模式告诉 Git 连工作目录的改动一起丢弃,只有在确定要放弃全部本地开发时才使用。

# 开始了一次疯狂的实验 # 新建 crazy.php 并写入代码 $ git add crazy.php $ git commit -m "Started a crazy dev" # 再次修改 crazy.php 以及大量其他文件 $ git add . $ git commit -m "Continued dev" # 测试后局面失控,决定整体回退 $ git reset --hard HEAD~2

git reset --hard HEAD~2把当前分支回退 2 个提交点,同时丢弃这两次提交产生的所有改动快照。

⚠️ 记住:如果提交已经推送到共享仓库,永远不要执行git reset --hard,否则会给仓库中所有协作者带来麻烦。此时应改用第八节的git revert

十一、创建 .gitignore 文件

对应文档:creating-a-gitignore-file.md

为什么需要 .gitignore

.gitignore是 Git 工作流的关键组件,告诉 Git 忽略哪些文件与目录,防止不必要或敏感的数据被纳入版本控制。以下几类文件不应入库:

  • 临时或系统生成的文件(缓存、构建产物、日志);
  • 可重新安装的大型依赖(如node_modules);
  • 个人或敏感配置(API 密钥、环境变量);
  • IDE/编辑器专属文件(如.vscode/.idea/)。

忽略它们能让仓库保持干净、减少冲突、避免安全风险。

创建方法

  1. 在项目根目录新建名为.gitignore的文本文件;
  2. 每行列出一个要忽略的文件或目录;
  3. 保存。

基本语法

  • *—— 通配符,匹配多个文件;
  • /—— 指定相对.gitignore的路径;
  • #—— 注释。

示例文件

# 忽略 Mac 系统文件 .DS_Store # 忽略依赖目录 node_modules/ venv/ # 忽略日志与缓存文件 *.log .cache/ # 忽略环境变量文件 .env # 忽略所有文本文件 *.txt

全局 .gitignore

所有仓库生效的全局忽略文件:

git config --global core.excludesfile ~/.gitignore_global

然后像编辑本地.gitignore一样编辑~/.gitignore_global

取消已跟踪文件的跟踪

文件在加入.gitignore之前若已被提交,需要先从跟踪中移除:

# 取消跟踪单个文件(保留在本地) git rm --cached filename # 取消跟踪所有被忽略的文件(-- 之后是路径,. 表示当前目录) git rm -r --cached . git add . git commit -m "Updated .gitignore"

撤销git rm --cached只需:git add filename

十二、存储凭据:git credential cache

对应文档:storing-credentials.md

每次访问远程仓库都要输入用户名密码确实影响效率,Git 提供了凭据缓存机制来解决。

⚠️ 安全提示:请务必遵守你工作/学习场所的安全策略。注意,credential.helper cache方式以明文把凭据保存在本机磁盘上,同一台电脑上的其他用户(例如恶意 NPM 模块)都可能读取到它。

全局凭据缓存(所有仓库)

git config --global credential.helper cache

仓库级凭据缓存

git config credential.helper cache

设置缓存超时

不指定时长时凭据可能被长期保留;用--timeout控制保存在内存中的时间:

git config credential.helper 'cache --timeout=<timeout>'

使用该 helper 时凭据不会落盘,超时后自动清除。默认值是 900 秒(15 分钟)。

十三、进一步学习资源索引

对应文档:Useful-links-for-further-learning.md

该文档是一份面向初学者与进阶者的学习资源索引,收录了 GitHub 官方文档、交互式 Git 练习工具、视频课程、命令速查表、合并冲突专题、rebase 图解、提交信息书写规范、开源贡献入门指南、版本控制课程以及编辑器内置 Git 功能说明等多类资料。当你完成本文全部练习后,可以继续翻阅这份清单:把交互式教程当作日常练习场,把速查表贴在案头,把提交信息规范应用到每一次git commit中,就能逐步形成更专业的协作习惯。

总结:把这些技巧串进真实的贡献流程

把本文的 13 个技巧放回 first-contributions 的真实贡献场景,你会看到一条完整的能力链路:

  1. 开发前先按第三节同步 fork,避免"落后 N 个提交";
  2. 提交后若发现信息有误或漏改,用第一节git commit --amend修正;
  3. 若提交到了错误分支,用第四节移动到正确分支;
  4. 若误提交了不该入库的文件,用第五节或第十一节从跟踪中移除;
  5. PR 合并后,用第六节清理本地与远程的临时分支;
  6. 若 PR 评审要求合并提交历史,用第九节 squash;
  7. 若遭遇冲突,按第七节逐文件解决;
  8. 若推错了提交,用第八节 revert(已推送)或第十节 reset(未推送);
  9. 最后用第十二节配置凭据缓存,避免频繁输入密码。

这些文档全部收录在 git_workflow_scenarios 目录下,除英文原版外,多数主题还提供了中文(如 amending-a-commit.zh-cn.md)、孟加拉语(additional-material.be.md)等多语言版本,可对照阅读。掌握这 13 个主题,你在任何开源项目中的协作都会更加从容。

【免费下载链接】first-contributions🚀✨ Help beginners to contribute to open source projects项目地址: https://gitcode.com/gh_mirrors/fi/first-contributions

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询