简介:面向 Git 初学者与日常协作开发者的命令速查资源,系统梳理 SSH 密钥配置、仓库克隆与更新、代码提交与还原、本地及远程分支管理、冲突解决、标签操作等核心场景,并延伸至 stash 工作现场暂存、rebase 分支整理等进阶用法,无论是个人项目还是团队协作,都能快速定位所需操作。覆盖 git clone、commit、reset、merge、rebase 等高频命令的完整语法与适用场景,适合作为随查随用的操作手册。压缩包内仅含 1 个 docx 文档,体积 349KB,内容以分节速查表形式呈现,便于按需检索对应命令。目前已有 378 人学习;文档针对工作区改动、已暂存、已提交未推送等不同状态分别给出还原方案,并列出解决冲突的标准流程,可帮助读者快速摆脱误提交、冲突无从下手等常见问题,提升日常开发与团队协作的效率。
1. 面对 Git 命令清单,先从使用顺序入手而不是背参数
Git 基本命令看起来散,其实有一条清晰的线:配置密钥、克隆代码、提交推送、分支合并、冲突解决、标签发布,每一步都在回答一个真实协作问题。这份资源不是把所有 Git 命令按字母排列,而是按照一个开发者的实际操作路径整理的,从 SSH 配置开始,一直覆盖到 reset、rebase、stash 和分支策略。它适合两类人:一类是刚接触版本控制的开发者,想快速拿到能跑通全流程的命令;另一类是已经用了很久但偶尔在还原文件、处理远程分支时犹豫的熟手,翻这类清单是为了确认参数的边界和副作用。接下来按这条链路逐个拆开,把命令能做什么、不能做什么、以及容易翻车的位置讲清楚。
2. 从 SSH 到首次克隆:先把本地服务器身份打通再动手
2.1 生成 SSH 密钥并完成连接测试
初次接触 Git 服务器,第一个动作不是 clone,而是确认服务器认你的身份。通过 HTTP 协议克隆通常需要每次输入账号密码,而配置 SSH 之后,推送和拉取都能走密钥认证,省掉重复输入。常见做法是执行 ssh-keygen 生成一对密钥,公钥放到服务器上,私钥留在本地。
ssh-keygen -t rsa -C "你的邮箱"执行后会提示设置密码,直接三次回车表示不设密码。-t rsa指定生成 RSA 算法密钥,-C后面追加一个注释,通常写邮箱,用于标识这把密钥的归属,不影响认证结果。生成的文件默认在用户目录下的.ssh文件夹中,私钥是id_rsa,公钥是id_rsa.pub。
这里有个很容易踩的细节:需要复制到远程仓库的是公钥id_rsa.pub里的内容,不是私钥。打开公钥文件复制全部字符,粘贴到远端仓库后台的 SSH key 配置区即可。
ssh git@<服务器IP>这条命令用于测试 SSH 连接。首次连接时终端会提示确认服务器指纹,输入yes后回车。如果返回一段欢迎信息并且能看到该用户名对应的说明,说明密钥配置生效。常见的失败情形是提示权限被拒绝(Permission denied),这时优先检查公钥是否完整复制、本地私钥文件权限是否过宽。ls -la ~/.ssh确认两个文件存在后,用ssh-add -l检查私钥是否被 SSH agent 加载,必要时执行ssh-add ~/.ssh/id_rsa手动添加。
2.2 clone 与 pull 的协议差异及分支参数
配置好 SSH 后,克隆仓库就分为两种方式。HTTP 克隆适合服务器还没配置 SSH key 的临时场景,SSH 克隆适合日常使用。
git clone http://<服务器IP>:端口/组名/仓库名.git git clone git@<服务器IP>:组名/仓库名.gitHTTP 方式会要求输入远程账号密码,每次推送拉取都可能弹认证;SSH 方式只要密钥配置有效,后续操作不再有交互式认证。端口号只出现在 HTTP 地址中,SSH 默认走 22 端口,若服务器修改过 SSH 端口,需要在地址里显式带端口,例如ssh -p 端口 git@<服务器IP>,但 clone 地址通常写为ssh://git@<服务器IP>:端口/组名/仓库名.git这种显式形式。
两种协议的差异更推荐用表格记录:
| 对比项 | HTTP 克隆 | SSH 克隆 |
|---|---|---|
| 认证频率 | 每次操作可能认证 | 配置后免密 |
| 地址构成 | 包含 IP 与端口 | 用户名加 IP |
| 适用场景 | 临时拉取 | 长期开发推送 |
| 防火墙友好度 | 通常好于 SSH | 依赖 22 端口开放 |
拉取远程更新时,命令需要带分支名:
git pull origin <分支名>origin是远程仓库的默认别名,<分支名>指定拉取哪个分支。执行 pull 前,本地工作区最好保持干净,如果本地有未提交的修改,并且这些修改涉及的文件刚好与远程更新冲突,pull 会报错并要求你先处理本地改动。所以我的习惯是:pull 之前先git status看一眼,有改动就先提交或临时 stash,再执行更新。
3. 提交工作流:diff、add、commit、push 的顺序不能乱
3.1 用 diff 精确确认改动内容
提交代码前最忌讳的事情是凭印象写提交说明。先看改了什么,再决定哪些文件参与本次提交,这条纪律能避免把调试代码夹带进版本库。
git diff不加参数的git diff比较的是工作目录与暂存区域之间的差异,也就是你已经修改但还没执行git add的内容。换句话说,它回答的问题是“我改了哪些文件、具体改了哪些行”。如果你想看已经git add过但还没提交的内容,用的是另一组参数:
git diff --cached git diff --staged这两条命令等价。它们的比较对象是暂存区域与上一次提交(HEAD)之间的差异,能看到已被标记为待提交的改动。这个区分很容易混淆,记住一个判断逻辑:还没 add 的改动看git diff,已经 add 的改动看git diff --cached,两者都想知道时直接执行:
git diff HEAD这条命令忽略暂存区状态,直接对比工作目录与最近一次提交,不管改动的文件有没有git add,都会展示出来。日常开发中我一般用git diff快速验证手头修改,用git diff --stat只看文件变更统计,避免大段输出干扰判断。
提交后想核对这次提交包含了哪些文件、每个文件增删了多少行,可以配合git log --stat -n查看最近几条提交的统计信息。
3.2 暂存、提交与推送:三个独立步骤的边界
git add <文件名> git commit -m "提交说明" git push origin <分支名>这三条命令执行的是三个不同阶段的操作。git add把文件放进暂存区,git commit把暂存区的内容固化成版本库中的一个新提交,git push把本地新提交推送到远程分支。很多人第一次接触 Git 时会误以为 commit 之后远程就更新了,实际上 commit 只发生在本地,没有 push 之前远程完全察觉不到。
git commit -a -m "注释"是一个快捷方式,它可以跳过显式git add,直接提交所有已跟踪文件的改动。但这里有边界:-a参数只对 Git 已经跟踪的文件有效,新增的未跟踪文件(untracked file)不会自动加入提交。所以我在需要一次性提交多个已跟踪文件时才会用git commit -a,涉及新文件时还是老老实实分两步。
常见做法是在提交前执行git status确认暂存区内容,避免把不想提交的文件混进去。git status的输出会列出三个区域的信息:尚未暂存的修改、已暂存可提交的修改、未跟踪的新文件。提交信息本身也值得养成习惯,尽量写清楚“做了什么”,不要只写“修改文件”,因为git log记录下来的信息是要留给未来排查问题用的。
3.3 push 之前先考虑要不要 pull
git push origin <分支名>推送时最常见的报错是“推送被拒绝,远程包含本地没有的提交”。这个现象说明远程分支上存在其他同事推送的新的提交,而你的本地分支基于旧节点,直接推会覆盖他人成果,Git 出于安全考虑直接拒绝。
解决路径很清晰:先git pull origin <分支名>把远程提交拉下来,再重新提交你的本地修改,最后 push。如果 pull 过程中出现代码冲突,Git 会标记冲突文件,手动修复后依次执行git add、git commit,再 push。养成先 pull 再 push 的习惯,尤其是多人共用一个分支时,这个顺序能减少大量冲突修复时间。
提交历史用的查看命令也在这里一起说明:git log默认按时间倒序列出全部提交,按q退出;git log --pretty=oneline会把每个提交压缩成一行,只显示哈希值和提交说明;git log --graph --pretty=oneline --abbrev-commit能以图形方式展示分支的合并路径,排查分支关系时最有用。
4. 还原与重置:checkout、reset、revert 各自能吃到哪一步
4.1 工作区文件还原:checkout 的不可逆风险
git checkout -- <文件名>这条命令把工作区中的指定文件还原到最近一次提交的状态。适用场景是:你改了某个文件,但改乱了,想放弃改动回到修改前。需要注意,这个操作会直接丢弃工作区中未暂存的修改,而且被丢弃的内容无法通过 Git 恢复。执行前先问问自己:这个改动真的不要了吗?
有个保守的检查办法:先执行git diff <文件名>查看改动内容,确认无误后再 checkout。如果改动已经git add进了暂存区,情况会复杂一些,因为上面的 checkout 命令只处理工作区与提交版本之间的差异,不会动暂存区内容。这时候需要先让暂存区释放文件,再回到工作区还原:
git reset HEAD <文件名> git checkout -- <文件名>git reset HEAD <文件名>的作用是把暂存区中的该文件移除,让它回到“已修改但未暂存”的状态,文件内容本身不变。之后再执行 checkout 才能把工作区内容切回提交版本。这就是还原文件时最容易被绕晕的两步流程,很多初学者只执行了 checkout,发现文件没有变化,就是因为暂存区还占着一个副本。
4.2 reset 的三个模式:soft、mixed、hard
git reset是 Git 里功能最多也最危险的一组命令,它本质上是移动 HEAD 指针的位置。资源文档中提到三种模式:--soft、--mixed、--hard,它们的差异在于移动指针的同时,对暂存区和工作区的处理力度不同。
git reset --soft HEAD~1 git reset --mixed HEAD~1 git reset --hard HEAD~1--soft只回退提交记录,暂存区和工作区的文件内容都不变。也就是说,上一次 commit 的内容会回到暂存区,再执行一次git commit就能创建新的提交,这个模式常用于“刚才提交错误地包含了文件,想重新提交”。--mixed是默认模式,回退提交记录的同时清空暂存区,但工作区文件内容保留,修改会变成未暂存状态。--hard最激进,提交记录、暂存区、工作区全部回退到指定版本,工作区的源码会直接变成旧版本内容。
这三个模式的记忆方式可以简化为:soft 只动指针,mixed 动指针和暂存区,hard 三样全动。
| 模式 | HEAD 指针 | 暂存区 | 工作区 |
|---|---|---|---|
| --soft | 回退 | 保留 | 保留 |
| --mixed | 回退 | 清空 | 保留 |
| --hard | 回退 | 清空 | 清空 |
实际使用中,git reset --hard是最需要谨慎的一条命令。执行后本地源码立即变为目标版本,所有在工作区中的未提交改动都会消失。但它并不是完全没救,git reflog是 Git 的后悔药,它记录了 HEAD 指针移动的历史,包括被 reset 丢弃的提交哈希值。
git refloggit reflog会列出最近所有 HEAD 变动记录,每一行都包含提交哈希和操作描述。假设你执行了git reset --hard <版本号>想回到某个老版本,发现回错了,想在刚才那个新版本上继续开发,直接去 reflog 里找到旧提交的哈希值,再执行一次git reset --hard <旧哈希>就能跳回来。这是 Git 工作中最实用的恢复技巧,没有之一。
4.3 HEAD^ 与 HEAD~1 的区别和正确用法
git reset --hard HEAD^和git reset --hard HEAD~1都能回退到上一个提交,但二者在语义上存在细微差别。HEAD^表示当前提交的父提交,HEAD~1表示往上数 1 个提交。在简单线性历史上两者等价,一旦涉及合并提交(merge commit),^指的是第一个父提交,而~是沿着第一父提交链向上走。
git reset --hard HEAD^ git reset --hard HEAD~3HEAD~3表示向上回退 3 个提交。这里有一个资源文档里容易误导人的地方:原文写的是向前回退到第 3 个版本,实际语义是从当前 HEAD 往回数 3 个版本,不是前进。执行前先跑git log --oneline确认目标提交的位置。如果已经 push 到远程分支,reset 本地版本后会和远程产生分叉,下次 push 会被拒绝,这时要评估是否真的需要重写公共历史。团队共享分支上应避免使用 reset 回退,改用git revert创建反向提交。
git revert HEAD会生成一个新提交,这个提交的内容是上一次提交的反向操作,等于用一次新提交抵消旧提交的改动。它的好处是不会移动历史指针,适合已经推送到远程的分支。资源文档中的 reset 和 revert 各有适用边界:本地未推送的提交用 reset,已推送的公共提交用 revert。
5. 分支管理:本地分支、远程分支与合并的完整生命周期
5.1 创建、切换与删除本地分支
分支操作是 Git 协作的核心。首先从已有分支创建新分支:
git branch <分支名> master<分支名>是新分支的名字,master是起点。这条命令只创建不切换,当前所在分支不变。想要创建并立刻切换过去,用checkout -b一步到位:
git checkout -b <分支名>-b参数的含义是创建分支后立即切换,等效于先执行git branch <分支名>再执行git checkout <分支名>。基于远程分支创建本地分支的常见写法是:
git checkout -b dev origin/dev这条命令会创建名为 dev 的本地分支,并跟踪远程的 origin/dev,之后的 pull 和 push 会默认关联远程 dev 分支。重命名分支用git branch -m <旧名> <新名>,注意重命名前最好确认没有其他人基于旧分支名做操作,因为改名只影响本地,远程分支名不会自动跟随。
删除分支命令:
git branch -d <分支名> git branch -D <分支名>-d只允许删除已合并的分支,如果分支还有未被合并的提交,Git 会拒绝并提示。-D是强制删除,不检查合并状态。这里有一个处理技巧:分支开发完并确认合并后,用-d是安全的;如果分支上的实验代码不想保留,直接-D,但删除后该分支独有的提交会从分支引用中消失,只能靠 reflog 或哈希值找回。
5.2 合并策略:fast-forward 与 --no-ff 的分歧
分支开发的最终目标通常是合并回主分支,先理解合并的两种方式。
git checkout master git merge <分支名>默认情况下,Git 执行的是快进式合并(fast-forward merge)。它的条件是主分支没有产生新的提交,此时 Git 直接把 master 指针移动到<分支名>指向的提交上,结果是历史保持线性,不会生成合并节点。
git merge --no-ff <分支名>--no-ff会强制产生一次正常合并,在 master 分支上生成一个新的合并提交节点,哪怕主分支可以直接快进。为什么团队策略经常推荐--no-ff?因为合并节点能保留“这条分支曾在某个时间点被合入主线”的记录,后续用git log --graph查看时,分支合并的边界清晰可见。默认的快进式合并会把分支历史压平,看不出来哪些提交属于一次功能开发。
合并过程中如果发生冲突,Git 会列出冲突文件。处理流程是:打开冲突文件,找到<<<<<<<、=======、>>>>>>>标记的冲突区域,手动保留需要的代码,删除标记符号,然后执行:
git add <冲突文件> git commit -m "解决合并冲突"注意解决冲突后的提交不需要再带什么特殊参数,直接正常提交即可。整个过程中git status会提示“未合并的路径”等状态,按提示逐个文件处理完再提交,不要漏掉未解决的文件。
5.3 远程分支:创建、删除与本地同步
把本地分支推送到远程,Git 会用分支名在远程新建同名分支:
git push origin <分支名>如果远程已有同名分支,这就是一次普通推送;如果远程没有,则自动创建。删除远程分支使用:
git push origin --delete <分支名>这条命令会删除远程对应的分支,但本地分支仍然保留,需要的话用前面的git branch -d单独处理。查看远程分支列表使用:
git branch -a git branch -rgit branch -a显示本地加远程的所有分支,git branch -r只显示远程分支。资源文档中提到远程分支显示为红色,这是终端默认配色,不同 Git 配置文件可能表现不同,不用作为判断依据。
本地分支列表和远程分支的对应关系偶尔会失真,比如其他同事删除了远程分支,本地执行git branch -a仍能看到过期的远程分支记录。解决办法是同步:
git fetch origin --prune--prune参数会在抓取远程更新的同时,清理本地已经失效的远程分支引用。它不会动工作区和当前分支的内容,是安全的常规维护命令。资源文档中提到的远程分支管理顺序建议是:先 fetch 同步,再检查分支列表,最后 push 新分支或删除旧分支。
6. 分支协作高频问题排查:冲突、rebase、stash、reset 的连带事故
6.1 合并冲突与 rebase 冲突的处理顺序不同
现象:执行git merge develop时,终端提示“自动合并失败,请修复冲突后提交”;执行git rebase origin/master时,同样提示冲突,但后续步骤不一样。
原因:merge 产生的冲突需要你手动修复文件后,执行 add 和 commit 来结束这次合并;rebase 产生的冲突在修复文件后,只需 add,不需要 commit,而是用git rebase --continue让 rebase 流程继续应用后续补丁。
git add <冲突文件> git merge --continuemerge 场景下,修复冲突并 add 后,可以用git merge --continue完成提交,也可以用git commit完成。rebase 场景下:
git add <冲突文件> git rebase --continue如果 rebase 过程中发现思路不对想退出,执行git rebase --abort,分支会回到 rebase 开始前的状态。这个区别是新人最容易卡住的地方:rebase 冲突修复后直接 commit 会破坏 rebase 的连续应用机制,正确动作是 add 后 continue。
6.2 reset --hard 后找不到提交
现象:执行git reset --hard <版本号>回退到旧版本,过了几个小时发现还需要旧版本之后的某个提交,但git log已经看不到那个提交了。
原因:git log只显示当前 HEAD 能追溯到的提交记录,hard reset 移动了 HEAD,原分支上的提交丢失了引用,变相成了“孤儿提交”。
解决:用git reflog查看 HEAD 的完整变动历史,找到丢失提交的哈希值,然后执行git reset --hard <哈希值>跳回去。
git refloggit reflog的输出会包含每次 HEAD 移动前的位置和操作记录。需要注意的是 reflog 记录的是本地操作,不会随 push 上传,所以它只能在当前仓库内找回内容。如果这个提交从未 push 过、而本机仓库又被清理过,那才是真正丢失。所以遇到 hard reset 前,我会先执行git log --oneline记录当前哈希,相当于给未来留一条退路。
6.3 stash 后现场丢失
现象:执行git stash储藏了未提交的改动,然后git stash list看不到任何记录,或者git stash pop弹出时报冲突,导致原本的改动无法直接拿回。
原因:git stash list为空,大概率是之前弹出了储藏并成功合并,储藏被自动删除;git stash pop报冲突,是因为工作区当前状态与储藏内容基于的提交版本不一致,Git 无法自动合并。
解决:如果储藏还在但 pop 冲突,先不要继续操作,手动修复冲突文件,处理完后执行git stash drop丢弃已经弹出的储藏记录,避免留下过期引用。如果储藏不在 list 里,去 reflog 里找临时提交哈希。stash 本质上是用临时提交保存现场,git fsck --lost-found也能找回一些孤立对象,但操作成本较高。
git stash pop git stash applypop会直接恢复并且删除储藏记录,apply恢复但保留记录。资源文档中的建议是:不确定现场是否能干净恢复时,优先用apply,确认无误后手动drop。这个习惯能防止一次性 pop 把改动直接写到工作区然后弹出冲突,导致现场与储藏记录都不完整。
6.4 rebase 后 push 被拒绝
现象:本地分支执行git rebase origin/master后,提交历史重写,执行git push origin <分支名>被拒绝,提示远程包含本地不存在的提交。
原因:rebase 会为当前分支生成全新的提交对象,原本已推送的提交被替代,远程分支与本地分支历史分叉,Git 拒绝非快进式推送。
解决:对于尚未推送到远程的本地分支,rebase 后 push 没有阻碍;对于已经推送到远程、且分支只有你自己在使用的场景,常见做法是强制推送,但后续其他人若基于旧提交继续开发,会被强制覆盖。更稳妥的方案是--force-with-lease,它会检查远程引用是否仍在你上次 fetch 的状态,是才允许覆盖,否则拒绝,给协作分支留一层保底。
git push --force-with-lease origin <分支名>在团队分支上我的原则是:尽量不重写公共历史,rebase 只用于本地分支整理,需要同步远程时优先 merge。
7. log、diff 与 tag 的组合:版本定位与发布的实操技巧
分支理顺之后,日常开发剩余的核心需求集中在两件事:快速定位某次改动,以及给版本打标记。先把最常用的一组 log 参数串起来看:
git log --graph --pretty=oneline --abbrev-commit这条命令输出一个分支拓扑图,每个提交只显示一行,哈希取短格式。排查分支合并关系时,它比默认 log 直观得多。如果最近一次提交改动了哪些文件、每处改了什么,用下面这条:
git log -p -n-n是查最近 n 条提交,-p显示每个提交的具体补丁内容。此时输出的信息量较大,但正好可以当作 code review 的本地自查工具。配合git log --stat -n只看改动文件统计,能快速判断某次提交涉及的范围是否合理。
diff 系列在版本定位中同样高频,三个常用维度:
git diff HEAD git diff --stat git diff <分支名>git diff HEAD用于对比当前工作区与最近提交之间的所有差异,未暂存和已暂存的改动都能看到;git diff --stat只输出文件清单和增删行数,适合快速扫一眼改动面大小;git diff <分支名>对比当前分支与目标分支的最新差异。注意最后一条的比较基准是两分支各自的 HEAD,不是工作区状态。跨历史版本对比用git diff <哈希1> <哈希2>,配合 log 里拿到的提交哈希使用。
代码发版时的操作链条一般是这样:
git tag -a v1.1 -m "Version 1.1" git push origin v1.1tag -a创建带注释的标签,-m写标签说明。轻量标签直接写git tag v1.1,只记录指向的提交,没有额外信息。查看全部标签用git tag,查看某个标签指向的提交和注释内容用git show <标签名>。资源文档里提到可以用git tag <标签名> <分支名>给指定分支的末梢打标签,也可以直接对准某个提交号。
发布流程中还需要注意标签推送的位置。git push origin <标签名>推送单个标签,git push origin --tags会把所有未推送的本地标签一次性推上去。删除本地标签用git tag -d <标签名>,删除远程标签用git push origin --delete tag <标签名>。这里有一个容易踩坑的点:标签删除后,指向的提交仍然存在,只是失去了标识。
发版前最后检查一遍提交状态,我通常会按这个顺序执行:
git status git log --oneline -5 git diff --stat先看工作区有没有遗漏的未提交文件,再确认接下来要发布的提交序列是否符合预期,最后看改动范围是否包含预期文件。这套检查流程在多人分支上尤其有效,能提前发现误提交的内容。资源文档中没有单独提炼过这套组合,但它的作用就是把状态查看、历史定位和差异确认串成一次标准体检。标签在推送前先本地创建并git show确认指向无误,再执行 push,避免把错误标签发布出去。
从那以后我每次准备提交或推送时,都强制自己先看一眼 status 和 log,在动 reset 或 rebase 之前必然留一条 reflog 记录。这份备忘的价值不在于每条命令多复杂,而在于它把“该在什么时候用哪个操作”整理得足够清楚,遇到拿不准的边界参数先回来翻一遍再动手。希望帮到你。
本文还有配套的精品资源,点击获取