Git 常用操作笔记
按日常开发流程整理 Git 配置、提交、分支、远程同步、撤销、stash 和日志排查等常用操作。
Git 是日常开发里绕不开的版本控制工具。命令很多,但真正高频使用的操作通常集中在几个场景:初始化仓库、提交代码、切分支、同步远程、撤销误操作、临时保存现场、处理冲突和查看历史。
Git 解决什么问题
没有版本控制时,项目很容易变成这样:
project-final
project-final-new
project-final-new-2
project-final-really-final
这种方式最大的问题是:你很难准确知道每个版本改了什么、是谁改的、为什么改,也很难稳定回到某个历史状态。
Git 解决的是版本记录和协作问题。它会记录:
修改了哪些文件
新增或删除了哪些内容
谁提交了这次修改
什么时候提交的
这次提交的说明是什么
所以 Git 不只是“保存代码”,而是把项目变化保存成一条可追踪、可回退、可对比的历史线。
Git 和 GitHub 的区别
Git 和 GitHub 不是一回事。
Git:安装在本地的版本控制工具
GitHub:托管 Git 仓库并支持团队协作的远程平台
只用 Git,不用 GitHub,也可以在本地完成版本控制:
git init
git add .
git commit -m "初始化项目"
GitHub 的价值在于把本地仓库放到云端,并提供协作能力,例如:
远程仓库
分支协作
Pull Request
Issue
代码审查
CI/CD 自动化
开源项目管理
除了 GitHub,GitLab、Gitee、Bitbucket 也能托管 Git 仓库。
先理解 Git 的几个区域
Git 的很多命令看起来复杂,本质上是在几个区域之间移动内容。
工作区 -> 暂存区 -> 本地仓库 -> 远程仓库
对应含义:
工作区:当前项目目录里的真实文件
暂存区:准备进入下一次提交的改动
本地仓库:已经 commit 的历史记录
远程仓库:GitHub、GitLab、Gitee 等服务器上的仓库
常见文件状态:
untracked:Git 还没有追踪的新文件
modified:已追踪文件被修改,但还没有放入暂存区
staged:改动已经放入暂存区,等待 commit
committed:改动已经提交到本地仓库
日常最常见的提交流程是:
git status
git add .
git commit -m "提交说明"
git push
配置 Git
查看当前配置:
git config --list
配置用户名和邮箱:
git config --global user.name "Your Name"
git config --global user.email "your-email@example.com"
只给当前仓库配置用户名和邮箱:
git config user.name "Your Name"
git config user.email "your-email@example.com"
查看某一项配置:
git config user.name
git config user.email
配置默认分支名:
git config --global init.defaultBranch main
创建和获取仓库
查看 Git 是否安装成功:
git --version
如果能看到类似 git version 2.x.x 的输出,说明本机已经可以使用 Git。
在当前目录初始化 Git 仓库:
git init
执行 git init 后,当前目录会出现一个隐藏的 .git 文件夹。它保存提交历史、分支、配置等内部数据,通常不要手动修改或删除。
克隆远程仓库:
git clone <repository-url>
克隆到指定目录:
git clone <repository-url> <directory>
查看远程地址:
git remote -v
添加远程仓库:
git remote add origin <repository-url>
修改远程仓库地址:
git remote set-url origin <repository-url>
查看状态和差异
查看当前工作区状态:
git status
用更简洁的格式查看状态:
git status -sb
查看工作区和暂存区之间的差异:
git diff
查看暂存区和上一次提交之间的差异:
git diff --cached
查看某个文件的差异:
git diff -- path/to/file
查看两个提交之间的差异:
git diff <commit-a> <commit-b>
添加和提交
添加指定文件到暂存区:
git add path/to/file
添加当前目录下所有改动:
git add .
交互式选择要暂存的改动:
git add -p
提交暂存区内容:
git commit -m "提交说明"
跳过暂存步骤,直接提交已经被 Git 追踪的文件:
git commit -am "提交说明"
修改最近一次提交的提交信息:
git commit --amend
把当前暂存区内容追加到最近一次提交:
git commit --amend --no-edit
git commit -am 只会处理已经被 Git 追踪的文件。新文件仍然需要先执行 git add。
分支操作
查看本地分支:
git branch
查看本地和远程分支:
git branch -a
创建新分支:
git branch feature/login
切换分支:
git switch feature/login
创建并切换到新分支:
git switch -c feature/login
老版本 Git 也可以使用:
git checkout -b feature/login
重命名当前分支:
git branch -m new-branch-name
删除已经合并的本地分支:
git branch -d feature/login
强制删除本地分支:
git branch -D feature/login
合并和变基
把目标分支合并到当前分支:
git merge <branch>
注意合并方向:git merge <branch> 是把 <branch> 的变化合并到当前所在分支。
git switch main
git merge feature/login
这表示把 feature/login 合并进 main。
如果两个分支修改了同一个文件的同一段内容,Git 可能无法自动判断该保留哪一份,于是产生冲突。冲突文件中通常会出现类似标记:
<<<<<<< HEAD
当前分支的内容
=======
被合并分支的内容
>>>>>>> feature/login
解决冲突的流程:
git status
# 打开冲突文件,手动保留正确内容,并删除冲突标记
git add .
git commit -m "解决合并冲突"
冲突不是 Git 出错,而是 Git 在提示:这里需要开发者自己判断最终内容。
把当前分支变基到目标分支:
git rebase <branch>
常见场景:在功能分支上同步 main 的最新代码。
git switch feature/login
git fetch origin
git rebase origin/main
如果 rebase 过程中发生冲突:
git status
# 手动解决冲突
git add .
git rebase --continue
放弃本次 rebase:
git rebase --abort
简单规则:
公共分支优先 merge,避免改写别人正在使用的历史。
个人功能分支可以 rebase,让提交历史更线性。
远程同步
拉取远程分支信息,但不自动合并:
git fetch origin
拉取并合并远程代码:
git pull
等价于:
git fetch
git merge
使用 rebase 方式拉取:
git pull --rebase
推送当前分支:
git push
首次推送新分支并建立 upstream:
git push -u origin feature/login
删除远程分支:
git push origin --delete feature/login
查看本地分支和远程分支的跟踪关系:
git branch -vv
撤销和回退
撤销工作区中某个文件的修改:
git restore path/to/file
撤销所有工作区修改:
git restore .
把文件从暂存区移回工作区:
git restore --staged path/to/file
撤销最近一次提交,但保留改动在暂存区:
git reset --soft HEAD~1
撤销最近一次提交,并保留改动在工作区:
git reset --mixed HEAD~1
撤销最近一次提交,并丢弃对应改动:
git reset --hard HEAD~1
reset --hard 会丢弃工作区内容,执行前一定要确认没有未保存的重要改动。
生成一个新的反向提交,用来撤销某次提交:
git revert <commit>
已经推送到公共分支的提交,优先使用 git revert,因为它不会改写历史。
删除和移动文件
删除文件并放入暂存区:
git rm path/to/file
停止追踪文件,但保留本地文件:
git rm --cached path/to/file
重命名或移动文件:
git mv old-name new-name
如果某个文件已经被提交过,后来才加入 .gitignore,需要先取消追踪:
git rm --cached path/to/file
git commit -m "停止追踪某文件"
临时保存现场 stash
保存当前未提交改动:
git stash
保存时加说明:
git stash push -m "临时保存登录页改动"
查看 stash 列表:
git stash list
恢复最近一次 stash,并从列表中删除:
git stash pop
恢复最近一次 stash,但保留在列表中:
git stash apply
恢复指定 stash:
git stash apply stash@{1}
删除指定 stash:
git stash drop stash@{1}
清空所有 stash:
git stash clear
如果希望把未跟踪的新文件也一起保存:
git stash -u
查看提交历史
查看提交日志:
git log
单行查看:
git log --oneline
带分支图查看:
git log --oneline --graph --decorate --all
查看最近 5 条提交:
git log -5 --oneline
查看某个文件的提交历史:
git log -- path/to/file
查看某次提交的详情:
git show <commit>
切到某个历史提交查看当时的代码:
git checkout <commit>
这时可能会进入 detached HEAD 状态,表示当前不在某个正常分支上,而是在一个历史提交点上查看代码。如果只是查看旧版本没有问题;如果要继续开发,应该基于它创建新分支:
git switch -c recover-from-old-commit
回到主分支:
git switch main
查看每一行最后是谁改的:
git blame path/to/file
查看所有 HEAD 移动记录:
git reflog
git reflog 很适合用来找回误删分支、误 reset 前的提交位置。
标签 tag
查看标签:
git tag
创建轻量标签:
git tag v1.0.0
创建带说明的标签:
git tag -a v1.0.0 -m "版本 1.0.0"
推送指定标签:
git push origin v1.0.0
推送所有标签:
git push origin --tags
删除本地标签:
git tag -d v1.0.0
删除远程标签:
git push origin --delete v1.0.0
常见场景速查
1. 新项目第一次提交并推送
git init
git add .
git commit -m "初始化项目"
git branch -M main
git remote add origin <repository-url>
git push -u origin main
2. 开发新功能
git switch main
git pull --rebase
git switch -c feature/login
# 修改代码
git add .
git commit -m "实现登录功能"
git push -u origin feature/login
3. 提交前检查改了什么
git status -sb
git diff
git diff --cached
4. 刚提交完发现漏了一个文件
git add missing-file
git commit --amend --no-edit
5. 本地改乱了,只想恢复某个文件
git restore path/to/file
6. 本地提交错了分支
先记录当前提交:
git log -1 --oneline
切到正确分支并应用提交:
git switch correct-branch
git cherry-pick <commit>
回到错误分支撤销那次提交:
git switch wrong-branch
git reset --hard HEAD~1
如果错误提交已经推送到公共分支,不要直接 reset --hard 后强推,应该先确认团队协作影响。
7. 想找回误删的提交
git reflog
git switch -c recover-branch <commit>
Pull Request 协作流程
在团队协作中,通常不建议直接把代码推到 main 分支。更常见的流程是:
从 main 创建功能分支
在功能分支上开发
提交并 push 到远程
在 GitHub 上创建 Pull Request
团队成员进行 code review
确认没问题后合并到 main
Pull Request 简称 PR,本质是:我在某个分支完成了一组修改,请团队检查并合并到目标分支。
创建 PR 时常见的两个概念:
base:目标分支,比如 main
compare:来源分支,比如 feature/login
也就是把 compare 分支的修改合并进 base 分支。
GitHub 会在 PR 页面展示:
包含哪些提交
哪些文件发生变化
哪些行被新增或删除
是否存在冲突
是否通过自动检查
PR 的价值不只是合并代码,更重要的是让代码进入稳定分支之前经过 review,降低问题直接进入主分支的风险。
一条完整的日常工作流
# 1. 回到主分支并同步远程最新代码
git switch main
git pull --rebase
# 2. 创建并切换到功能分支
git switch -c feature/login
# 3. 修改代码后检查状态
git status -sb
git diff
# 4. 添加到暂存区并提交
git add .
git commit -m "新增登录功能"
# 5. 推送到远程分支
git push -u origin feature/login
之后在 GitHub 上创建 PR。 如果 review 后需要继续修改,就在同一个分支上继续提交并推送:
git add .
git commit -m "根据 review 修改登录校验逻辑"
git push
PR 会自动更新。
初学时最容易混淆的点
git add 不是提交。它只是把修改放入暂存区,真正保存版本的是 git commit。
git commit 不是上传 GitHub。它只保存到本地仓库,上传远程需要 git push。
git fetch 不会直接改你的工作区文件。它只是下载远程更新信息;如果要拉取并合并,使用 git pull。
分支之间不会自动同步。你在 feature/login 上提交的内容,不会自动出现在 main,需要 merge、rebase 或通过 PR 合并。
git rebase 可以让历史更线性,但会改写提交历史。自己的本地功能分支可以用;多人共享的公共分支要谨慎。
几个使用习惯
提交前先看状态:
git status -sb
提交前先看差异:
git diff
git diff --cached
推送前同步远程:
git fetch origin
git status -sb
不确定某个危险命令会影响什么时,先创建一个临时分支:
git switch -c backup-before-reset
Git 的重点不是背命令,而是知道当前改动在哪个区域、下一步要把它移动到哪里。只要围绕“工作区、暂存区、本地仓库、远程仓库”这条线理解,常见操作都会清晰很多。