从零掌握Git:安装配置到提交Pull Request的全流程指南
2026/9/20 2:20:31 网站建设 项目流程

1. 从零开始装好Git:下载、安装与配置的第一个门槛

很多人第一次接触Git,是在某个开源项目页面上看到一个“Fork”按钮,或者在同事的电脑上瞄到一串看着很唬人的命令行。然后自己跑去下载、安装、配置,等到真正想提交代码的时候,才发现前面好几个看似无关紧要的步骤没做对,后面每一步都在还债。

我先说结论:Git的安装本身很简单,但安装时的选项、安装完成后的全局配置,才是决定你后续贡献流程顺不顺畅的关键。这篇我打算完全按照一条真实贡献路径来写——从下载安装,到第一次提交,再到给开源项目提Pull Request,把中间所有你一定会踩到的细节都铺开讲清楚。

1.1 Git是什么,为什么贡献代码绕不开它

Git是一个分布式版本控制系统,通俗点理解,它就是给你整个项目装了一台“时光机”。每一次你主动保存(commit)的改动,都被记录成历史节点。这台“时光机”不只装在你自己电脑上,团队的每个成员电脑上都有一份完整的历史副本,这就是“分布式”三个字的含义。

在开源协作的场景里,Git的意义更直接。一个项目可能有几千人同时关注,几十人同时修改,大家互相之间根本不认识。如果没有一套清晰的版本管理规则,代码改造成什么样完全没法追踪。Git解决了三个核心问题:谁改的、改了什么、能不能回退。现在几乎所有主流代码托管平台,包括GitHub、GitLab、Gitee、Bitbucket,底层用的都是Git。

所以你在任何社区提问“怎么给开源项目贡献代码”,得到的第一个回答永远是:先学会Git。

1.2 各平台下载与安装:别选错版本,也别乱点下一步

先聊下载。网上搜索Git,会看到各种“Git中文版”“Git绿色版”的下载站,我个人的建议是不要碰它们。直接去Git官方网站git-scm.com下载,这是唯一可靠渠道。官网会根据你的操作系统自动推荐下载文件,Windows选64-bit版本即可,绝大多数现代电脑都是64位系统。

Windows安装时一路Next也不是不行,但有三个选项值得停下来看一下:

  • 选择默认编辑器:安装时会让选编辑器,推荐选VS Code或者Nano。别选Vim,不是Vim不好,是新手在提交时会卡在Vim的编辑界面里出不来,我曾经见过有同事提交信息里莫名其妙留了一堆Vim的操作痕迹,就是因为不会退出编辑器,被迫乱按一通导致的。
  • 调整PATH环境变量:务必选择中间选项“Git from the command line and also from 3rd-party software”,这样Git命令才能在CMD、PowerShell、Git Bash里通用。有时候装完在PowerShell敲git --version提示找不到命令,十有八九是这一步选错了。
  • 换行符处理方式:默认选项是“Checkout Windows-style, commit Unix-style line endings”,保持默认就好。这条规则解决的是Windows和Linux/macOS换行符不一致的问题,默认选项能自动把你本地的CRLF转换为仓库里的LF,是绝大多数项目采用的标准。

macOS用户最简单的方式是执行brew install git,Homebrew会自动装好最新稳定版。Linux用户用发行版自带源安装即可,Debian/Ubuntu系列执行sudo apt install git,RedHat/CentOS系列执行sudo yum install git

注意:不管什么平台,装完以后打开终端执行git --version,能看到git version 2.xx.x这样的输出,就说明安装成功了。如果没有输出,先检查PATH,再检查是不是安装包没下完整,不要急着往下走。

1.3 安装完成后的“隐藏任务”:命令行基础与Git Bash

Windows用户安装Git时会顺带装上一个“Git Bash”程序,这个环境比系统自带的CMD更适合跑Git命令,它模拟了Linux的终端操作方式,很多命令的体验和macOS/Linux一致。我建议Windows用户后续所有Git操作都从Git Bash进入,不要用CMD跑。原因是lspwdmkdir这些基础命令在Git Bash里都能用,而在CMD里是完全不一样的一套语法,两边来回切换非常容易混乱。

第一次打开Git Bash,你可能会看到路径显示成/c/Users/你的用户名,这是Unix风格的路径写法,对应Windows的C:\Users\你的用户名。记住这个对应关系,后面配置SSH密钥、切换目录时会频繁用到。

2. 第一次提交前必须做好的本地准备:配置、SSH与仓库初始化

安装只是开始。真正让Git知道“你是谁”、让代码托管平台信任“你提交的代码属于你”,靠的是下面的配置环节。这一步不做好,你会遇到两类经典问题:提交信息里没有正确的作者信息,以及推送代码时反复要求输密码。

2.1 全局配置user.name和user.email:Git的“身份ID”

Git要求每次提交都带着作者信息,这套信息由user.nameuser.email两个配置项决定。安装完Git后,第一次提交前,先执行:

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

这里的“你的名字”和“你的邮箱”,建议直接使用你在代码托管平台注册时用的信息。GitHub等平台会把提交记录和账号关联起来,如果你的提交邮箱和账号邮箱不一致,提交记录就不会显示在你账号的贡献图上,贡献了等于白贡献。

--global参数表示全局生效,也就是这台电脑上所有仓库默认都用这套身份。如果某个特定项目想用不同的身份,可以进入仓库目录后去掉--global单独设置:

git config user.name "项目专用名字" git config user.email "项目专用邮箱"

检查当前配置,执行git config --list,可以看到所有生效的配置项。我接手新电脑的第一件事就是执行这条命令,确认身份配置没问题再开始干活。

2.2 配置SSH密钥:免密推送的核心

平时我们从托管平台克隆项目,有两种地址可选:HTTPS地址和SSH地址。HTTPS地址第一次push时会要求输入用户名和密码(或者Personal Access Token),非常烦人。SSH地址则一次配置,后续永久免密。所以强烈建议走SSH。

生成SSH密钥的命令:

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

执行后一路回车即可。它会在~/.ssh/目录下生成一对密钥:id_ed25519是私钥,留在本机;id_ed25519.pub是公钥,需要复制到托管平台。

查看公钥内容:

cat ~/.ssh/id_ed25519.pub

复制输出的整行内容,打开你的代码托管平台(GitHub为例),依次进入Settings -> SSH and GPG keys -> New SSH key,把公钥粘贴进去保存。然后验证连通性:

ssh -T git@github.com

看到Hi 你的用户名! You've successfully authenticated类似的提示,就说明SSH配置成功了。

经验之谈:那台电脑如果换了用户目录,或者重新装了系统,~/.ssh就清空了,需要重新生成密钥并到平台重新添加。很多人换完电脑突然push不了代码,基本都是这个原因。

2.3 初始化本地仓库并完成第一次提交

配置完成后,我们来体验一次最完整的本地提交流程。先建一个测试目录:

mkdir git-practice cd git-practice git init

执行git init后,目录里会生成一个隐藏的.git文件夹,所有版本信息都存在这里。注意不要手动去修改或删除这个文件夹,否则仓库就废了。

接下来创建一个文件,并把它加入版本管理:

echo "# Git Practice" > README.md git add README.md git commit -m "docs: add readme"

git add把文件放入暂存区,git commit把暂存区内容正式提交成一个历史版本。提交后的输出会显示一条带哈希值的记录,比如[master (root-commit) a1b2c3d] docs: add readme,这个哈希值就是这次提交的唯一标识。

注意我用的提交信息格式是docs: add readme,这是目前开源社区最主流的提交规范之一,前缀用来说明类型。docs表示文档改动,feat表示新功能,fix表示修Bug,refactor表示重构,test表示测试相关。维护者通过扫描提交信息头部就能快速判断这次改动的性质,强烈建议从一开始就养成这个习惯。

2.4 理解三大区域:工作区、暂存区、版本库

如果不理解Git的区域模型,后面非常多命令都会觉得“玄学”。用生活化类比来说:

  • 工作区是你电脑里能看到的那个目录,你在这里正常编辑文件。
  • 暂存区是一个中间缓冲区,相当于一个待提交清单,git add的作用就是把“我想提交这个文件的当前状态”写进清单。
  • 版本库是Git真正保存历史版本的地方,git commit把暂存区的内容固化成历史记录。

很多Git操作题其实就是在这三个区域之间搬东西。git add是把文件从工作区搬到暂存区,git commit是把暂存区搬到版本库,git checkout可以把版本库里的内容搬回工作区。理解了这个模型,后面看git reset的各种参数会清爽很多。

3. 开源项目贡献的标准流程:从Fork到Pull Request

现在进入全篇最核心的部分。假设你已经在代码托管平台上发现了一个想参与的开源项目,比如一个数据处理库、一个前端UI组件库,你想给它提一个功能增强或修一个Bug,完整流程是什么?我用文字描述整个路径,再逐个环节拆开讲:

  1. 点击原项目页面右上角的“Fork”按钮,把项目复制到你自己的账号下。
  2. git clone你账号下的这个仓库副本到本地。
  3. 在本地把原项目仓库地址添加为upstream远程源。
  4. 创建专属的功能分支。
  5. 修改代码、测试、提交。
  6. 推送到你自己账号下的远程分支。
  7. 在托管平台发起Pull Request(不同平台叫法不一样,Gitee叫“Pull Request”,GitLab叫“Merge Request”,本质相同)。
  8. 等待维护者审查,根据反馈继续修改。

3.1 Fork:为什么要“转一道手”而不是直接提交

如果是项目核心成员,确实可以直接创建分支推送,但普通外部贡献者没有原仓库的写入权限。Fork的本质是在平台层面给你复制出一份完整的仓库,拥有这份副本完全属于你的账号,你有权限随意推送。

这套机制的聪明之处在于:原项目保持稳定,所有外部改动都在各自的副本上进行,只有经过维护者审核的改动才会通过Pull Request合并回原项目。它解决了“如何让陌生人参与协作且不破坏主项目”的问题。

点击Fork按钮时,如果项目很大,平台会需要几秒钟做后台复制。完成后你会进入一个URL中带着你用户名的项目页面,那就是你的Fork副本地址。

3.2 Clone:把远程仓库搬到本地

Fork完成之后,复制你的副本仓库的SSH地址,执行:

git clone git@github.com:你的用户名/项目名.git

git clone会自动完成三件事:在当前目录创建一个同名文件夹、把仓库历史完整下载下来、自动创建一个名为origin的远程地址标识,指向你克隆时的源地址。

克隆完成后先进入目录:

cd 项目名 git remote -v

git remote -v可以看到当前仓库关联的远程地址。刚克隆完通常只有一个origin,指向你账号下的Fork副本。

3.3 添加upstream并同步上游更新

这里有一个新人很容易漏掉的关键步骤:没有把原项目的地址添加为远程源。你Fork出来的副本只是某一时刻原项目的快照,原项目的维护者每天可能合并几十个提交,你的副本会越来越“老”。为了解决这个问题,需要手动添加一个名为upstream的远程源指向原项目:

git remote add upstream git@github.com:原项目所有者/原项目名.git

再执行git remote -v,应该能看到两个远程地址:

  • origin:你账号下的Fork副本。
  • upstream:原项目官方仓库。

日常工作流中,upstream用来拉取原项目最新代码,origin用来推送你的改动。两者分工明确。

3.4 创建功能分支:不要在main分支上直接干活

正式开发前,先把分支切换到main并同步到最新:

git checkout main git pull upstream main

git pull upstream main会从原项目拉取最新代码并自动合并到本地main分支。这是贡献代码前最重要的一步准备工作,它能最大程度避免你和原项目代码脱节。

接下来创建功能分支:

git checkout -b fix/login-bug

-b表示创建并切换分支,fix/login-bug是分支名。分支命名有约定俗成的风格:用fix/开头表示修Bug,feat/表示新功能,docs/表示文档改动,斜杠后面用短横线描述任务。我见过很多新人直接在main上改代码,最后push和提PR的时候仓库历史和上游完全冲突,处理起来非常痛苦。养成“一个分支只做一件事”的习惯,是专业开发者的基本素养。

3.5 提交代码的实操细节:小步提交,确保可追溯

分支创建好后,开始修改代码。无论改什么,都遵循以下小循环:

  1. git status查看当前改动状态。
  2. 确定需要提交的文件范围。
  3. git add 具体文件(避免无脑git add .)。
  4. git diff --cached检查暂存区内容。
  5. git commit -m "fix: correct login error handling"提交。

git add .确实便捷,但风险在于把不想提交的文件也纳入进来。比如本地调试产生的临时文件、自动生成的配置文件,一旦被提交,后面又得通过git rm等操作清理。更好的习惯是单独指定文件,或者在项目根目录维护一份.gitignore文件,提前把不需要纳入版本管理的目录和文件排除。

git commit之后,检查提交历史:

git log --oneline

输出每一行代表一次提交,比如:

3f2a9e1 fix: correct login error handling 9c8b4f2 docs: update readme 6d51209 feat: add user profile page

提交历史清晰、粒度适中(每次提交只做一件事),维护者在review你的PR时会舒服很多。反过来,如果你把所有改动揉到一个提交里,对方根本没法逐行判断哪些改动和你的主题相关,被拒的概率直线上升。

3.6 Push到远程并发起Pull Request

本地提交完成后,推送功能分支到你的Fork副本:

git push -u origin fix/login-bug

-u--set-upstream的简写,意思是把本地分支和远程分支建立关联,后续在这个分支上直接执行git push即可,不用再重复指定远程和分支名。

推送成功后,托管平台通常会自动识别到你刚推送的分支,并在页面顶部出现“Compare & pull request”按钮。点击进入Pull Request页面,填写标题和描述。

PR描述的基本模板:

  • 改动类型:Bug修复还是新增功能。
  • 改动内容:你具体改了哪些文件、哪些逻辑。
  • 测试方式:你做了什么测试,本地跑过哪些用例。
  • 关联Issue:如果原项目有对应的Issue编号,写上Closes #123,合并时会自动关闭对应Issue。

PR提交后,维护者可能会评论要求修改。修改完成后继续在同一个分支上提交并推送,PR会自动更新。除非维护者明确要求,否则不要在PR过程中擅自闭合再重开一个新的PR。

4. 高频Git命令实操速查与踩坑提示

日常贡献过程中,高频使用的Git命令其实就那么二三十个。这里按使用场景整理一份速查表,每个命令都附上关键参数和个人经验提示。

4.1 全局配置与信息查看

命令作用我的提示
git config --global user.name "名字"配置全局用户名和托管平台账号保持一致
git config --global user.email "邮箱"配置全局邮箱用注册平台的邮箱才能关联贡献图
git config --list查看所有配置排查问题时先看它
git status查看工作区状态我写过无数次,但每次提交前都会再看一遍
git log --oneline --graph --all查看完整提交历史图谱--graph能显示分支合并结构

4.2 文件操作与暂存区管理

git add有集中常见用法:

git add filename.txt # 暂存指定文件 git add src/ # 暂存整个目录 git add . # 暂存所有改动(慎用) git add -p # 交互式分段暂存,只暂存文件的部分改动

git add -p是我特别想推荐给新人的命令。当你一个文件里既有格式化产生的无关改动,又有核心逻辑改动时,用-p可以逐块选择哪些改动暂存、哪些不暂存。这在提交规范比较严格的项目里几乎是必备技能。

4.3 撤销与回滚:reset、checkout、revert的抉择

撤销类命令是新手最容易踩坑的地方,因为git checkoutgit resetgit revert表面上看都在“撤销”,但作用对象完全不同。

  • git checkout -- filename:丢弃工作区中某个文件的修改,回到最近一次提交的状态。该操作不可恢复,执行前确认自己真的不需要这些改动了。
  • git reset --soft HEAD~1:撤销最近一次提交,但保留改动在暂存区。适合“提交信息写错了”或“想重新分组提交”的场景。
  • git reset --mixed HEAD~1:撤销最近一次提交并保留改动在工作区,需要重新git add。适合“提交后发现文件加少了”的场景。
  • git reset --hard HEAD~1:撤销最近一次提交,同时丢弃所有改动。危险操作,慎用,除非你确切知道自己在做什么。
  • git revert HEAD:正向新增一个提交,用来反向去掉旧提交的改动。适合已经推送到远程、需要撤回的场景,因为它不改写历史。

在推送代码到远程之前,用reset改写本地历史没有副作用;但代码一旦推送出去并被别人拉取,就不要再reset了,应该用revert,否则会破坏别人仓库的历史一致性。

4.4 分支操作:branch、switch、merge

现代Git推荐用git switch替代git checkout来切换分支,语义更清晰:

git branch -a # 查看所有分支,包括远程分支 git switch -c feature/x # 创建并切换到新分支 git switch main # 切换到已有分支 git merge feature/x # 把feature/x合并到当前分支 git branch -d feature/x # 删除本地分支(需先合并) git push origin --delete feature/x # 删除远程分支

4.5 合并冲突:看见冲突标记别再慌

合并分支或拉取更新时如果出现冲突,Git会在冲突文件里插入特殊的标记:

<<<<<<< HEAD 当前分支的内容 ======= 合并进来分支的内容 >>>>>>> feature/x

<<<<<<< HEAD=======之间是当前分支的版本,=======>>>>>>>是另一个分支的版本。你要做的事很朴素:手动打开文件,保留想要的内容,删除冲突标记,然后重新git addgit commit

冲突本身不可怕,可怕的是对冲突的恐惧导致不敢合并、不敢拉取,最后分支越来越落后,冲突越积越多。我的经验是,冲突来得越早越容易解决。每天开始工作前先git pull upstream main,能让绝大多数小冲突在第一时间暴露出来,趁着对代码还有记忆的时候处理。

5. 贡献过程中最常见的坑与排查技巧实录

最后这部分,我把这些年实际带团队、参与开源项目过程中遇到的高频问题集中整理出来。每一个都是真实发生过的场景,对应当时的排查思路和最终解法。

5.1 提交信息写错了怎么办

场景:提交后立刻发现信息有错字,或者漏描述了某些文件;再或者刚提交完又改了一个小地方,不想留下两条“垃圾提交”。

解法:如果是最近一次提交,用git commit --amend修正:

git commit --amend -m "fix: correct login error handling logic"

它会用新的提交覆盖最近一次提交。如果这个提交已经推送到了你的远程分支,amend之后需要强制推送:

git push --force-with-lease

如果错的是更早的多次提交,那就需要用到git rebase -i交互式变基,把提交列表里需要修改的那一行从pick改为editreword。这个操作对新手来说有点复杂,建议先在草稿仓库练习几遍再在真实项目上操作。

5.2 分支落后导致无法合并

场景:你的PR被维护者挂了两周,期间原项目合并了大量别人的代码,你的分支成了“老古董”,平台提示“This branch has conflicts that must be resolved”。

解法:回到本地,同步上游,再变基或合并:

git checkout fix/login-bug git fetch upstream git rebase upstream/main

rebasemerge都能拿到上游最新代码,区别在于合并历史的表现:merge会多产生一个“Merge remote-tracking branch”的合并提交,rebase则把你本地提交像“剪辑”一样重新放到最新代码的顶部,历史更线性。对于PR场景,我强烈推荐用rebase,因为提交历史干净,维护者review时会觉得很舒服。

rebase过程中如果遇到冲突,解决方式与普通冲突类似,区别是解决完每个冲突后执行git rebase --continue,而不是直接git commit。如果中途想放弃这次变基,git rebase --abort可以完全回到操作之前的状态。变基完成后,同样需要强制推送更新远程分支。

5.3 把不该提交的文件提交上去了

场景:把本地临时文件、密钥文件、甚至几百MB的二进制打包文件推到了远程。前者属于“卫生问题”,后者属于“事故现场”。

解法:立即在项目根目录创建或更新.gitignore文件,把这类文件写入排除规则:

*.tmp *.log .env node_modules/ dist/

但这只对“未来”有效,已经被Git跟踪的文件不会自动移除。需要先把它们从Git索引中移除:

git rm --cached filename

--cached表示只从Git索引移除,保留磁盘上的文件本身。然后用git commit提交移除记录,再推送。

如果是密钥文件,节奏还要更快:提交密钥的瞬间就该认定它已经泄露,不要在Git历史上删删改改,而是立刻到相关平台吊销并重新生成密钥,同时把密钥文件加入.gitignore

5.4 历史提交里有大文件怎么办

如果不小心把一个几百MB的文件推到了远程会发现一个很尴尬的问题:哪怕用git rm删除了,历史记录里它仍然存在,仓库体积依然很大。因为Git保存的是完整历史,而不仅仅是当前状态。

处理思路:使用git filter-branch或新工具git filter-repo改写历史,彻底从所有历史提交中抹除这个大文件。这个操作会改变提交哈希,意味着远程仓库历史需要强制推送,并且所有协作者都必须基于新历史重新操作,影响面非常大。

我的建议只有一个:推送到远程前先控制好这次提交的内容。git status检查待提交文件列表,用.gitignore排除无用文件,提交前看一遍git diff --stat确认改动规模是否合理。这比事后清洗历史省力一万倍。

5.5 提完PR后老被要求修改,心态和节奏怎么把握

PR被要求修改是常态,不代表你不行。维护者提评论的理由有很多:代码风格不匹配、测试用例缺失、文档没更新、命名不够清晰。遇到这种情况,先把评论一条条看完,然后在同一分支上继续修改提交并推送:

git add . git commit -m "fix: adjust code style per review" git push

不必为了“PR看起来很干净”而急着做rebaseamend把多个提交压缩成一个。维护者更在意的是改动本身是否合理,以及你反馈的速度。等PR最终被接受后,维护者自己会选择“Squash and merge”等方式统一整理提交历史。

5.6 一个非常实用的小习惯:提交前先看diff

不管新人还是老手,完全可以养成一个高频习惯——在每条Git命令之间,每隔几步就停下来看一眼git diff执行git add前看工作区diff,执行git commit前看git diff --cached,执行git push前看git log确认提交内容。

每次提交都确认“我提交的确实是我想让别人看到的东西”,可以过滤掉绝大多数失误。这个习惯的成本几乎为零,收益却实实在在地避免过无数次面向“我不小心push错了”的尴尬。

我个人在实际项目里还有一个私藏的小习惯:给经常操作的远端加一个简短别名,比如git remote add origin2这种命名虽然随意,但在多个remote之间切换时会方便很多。另一个建议是每执行一条可能有破坏性的命令(reset --hardrebaseforce push)之前,先做一次git branch -a确认当前所在分支和要操作的目标,在脑内过一遍这条命令会发生什么再动手。Git把回旋余地留给了谨慎的人,而不是大胆的人。

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

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

立即咨询