git指令速记
发现自己此前学习过于不仔细,闹了笑话。重新学了一遍,了解了许多用法,分清了概念,此处记录。
文章由AI生成,除了我学习时发现容易搞混搞错的点加了几个说明,基本没动。
概念
git的提交是增量提交,所以删除前面的提交或者修改不代表后续的提交就没用了。
git的分支实际上是一个符号,指向一个节点上,而不是指一串节点。
HEAD是指当前指向的节点,是一个特殊符号。
许多操作只是在把一个提交改为了另一个提交,比如说amend一个提交后,A变成了A’,但是不代表A本身在历史是不见了,在git的历史记录和缓存中仍然保留,如果有什么大文件在里面,需要着重注意。已经因为这个搞出笑话了。(所以提交前要检查,至少提交是提交节点链的)
本地的远程分支和远程仓库的状态是不同的,要牢记这一点,二者绑定在一起而已(当然这个可以修改)
勿随意破坏提交链,切记
好习惯
提交相关
- 提交粒度要合理
一个提交只做一件事(如 “修复登录按钮样式”“新增用户列表接口”),避免一次提交包含多个不相关的修改。这样后续回滚或查看历史时更精准。
❌ 不好:git commit -m "修改了一堆东西"
✅ 推荐:git commit -m "fix: 修复移动端登录按钮点击无响应问题" - 提交信息要规范
用简洁明了的语言描述 “做了什么”,最好遵循约定式提交(Conventional Commits):feat: 新增xxx功能(新功能)fix: 修复xxxbug(bug 修复)docs: 更新接口文档(文档修改)refactor: 重构用户模块代码(代码重构,不影响功能)
避免模糊描述(如 “改了点东西”“更新”)。
- 提交前检查修改内容
提交前用git status确认要提交的文件,用git diff检查具体修改内容,避免误提交敏感信息(如密码、密钥)或无关文件(如日志、临时文件)。
分支管理
- 使用有意义的分支命名
分支名应体现用途,例如:feature/user-login(新功能:用户登录)bugfix/payment-error(bug 修复:支付错误)hotfix/security-vulnerability(紧急修复:安全漏洞)
避免dev1、test等模糊名称。
- 保持主分支稳定
main/master分支应始终保持可部署状态,开发新功能时从主分支创建新分支,完成后通过 PR/MR 合并,合并前必须经过代码 review 和测试。 - 定期同步主分支更新
在功能分支开发时,定期从主分支同步最新代码(git merge main或git rebase main),避免后期合并时出现大量冲突。
协作相关
- 推送前先拉取(pull)
推送本地修改到远程前,先用git pull拉取远程最新代码,解决本地与远程的冲突后再推送,减少远程仓库的冲突概率。 - 不强行推送已公开的历史
已推送到远程的提交,不要用git push --force强行覆盖(除非团队明确约定),这会导致其他协作者的本地仓库混乱。若需修改已推送的历史,优先用git revert而非git reset。 - 及时清理无用分支
功能上线或 bug 修复后,删除对应的本地和远程分支(git branch -d <分支名>、git push origin --delete <分支名>),避免分支过多导致混乱。
撤销与备份
- 谨慎使用
git reset --hard
该命令会彻底删除工作区和暂存区的修改,执行前务必确认没有需要保留的未提交内容,可先用git stash暂存(git stash save "临时暂存"),后续用git stash pop恢复。 - 善用
git reflog备份操作记录
所有分支切换、提交、重置等操作都会被git reflog记录,即使误删提交,也能通过它找到历史哈希值恢复(git reset --hard <哈希>)。 - 重要节点打标签(tag)
发布版本时,用标签标记重要提交(git tag -a v1.0 -m "正式发布v1.0版本"),方便后续追溯特定版本的代码。
配置与工具
-
设置全局用户名和邮箱
确保提交记录归属正确:git config --global user.name "你的名字" git config --global user.email "你的邮箱"不同项目可单独设置本地配置(去掉
--global)。 -
使用
.gitignore忽略无关文件
在仓库根目录添加.gitignore文件,指定无需跟踪的文件(如node_modules/、*.log、IDE 配置文件等),避免提交垃圾文件。可在 gitignore.io 生成模板。 -
定期清理 Git 缓存
用git gc清理无用的对象数据,减小.git文件夹体积(Git 会自动执行,但手动执行可优化性能)。
初始化和克隆
init,clone
远程
git remote # 查看远程仓库名称(默认通常是origin)
git remote -v # 查看远程仓库详细链接(fetch/push地址)
git remote add origin https://github.com/example/repo.git # 添加远程仓库
git remote set-url origin https://new-url.git # 修改远程仓库链接git fetch origin # 拉取origin远程的所有分支更新
git fetch origin main # 只拉取远程main分支的更新git pull origin main # 拉取远程main分支并合并到当前分支
git pull --rebase origin main # 拉取后用rebase方式合并(替代merge,保持历史整洁)git push origin main # 推送本地main分支到远程main分支
git push -u origin dev # 推送本地dev分支并关联远程dev分支(后续可直接git push)
git push origin --delete dev # 删除远程dev分支
工作区和暂存区
git add filename.txt # 添加单个文件
git add dir/ # 添加整个目录
git add . # 添加当前目录所有修改(不包括删除的文件)
git add -u # 只添加已跟踪文件的修改和删除(不包括新文件)
git add -A # 添加所有修改(包括新文件、删除文件,等同于git add . && git add -u)git status # 详细状态
git status -s # 简洁输出(A:新增,M:修改,D:删除)git restore filename.txt # 撤销工作区的修改(恢复到暂存区状态)
git restore --staged filename.txt # 将暂存区的修改撤回到工作区git rm filename.txt # 删除文件并暂存
git rm --cached filename.txt # 仅从暂存区删除(保留本地文件,停止跟踪)
restore --source=[version] [file]:恢复当前文件状态为指定版本,而且直接暂存
提交
git commit -m "提交说明" # 直接添加提交信息
git commit -am "提交说明" # 跳过暂存区,直接提交已跟踪文件的修改(不包括新文件)
git commit --amend # 修改最近一次提交(可修改信息或补充暂存的修改)
分支
git branch # 查看本地分支(当前分支前有*)
git branch dev # 创建dev分支
git branch -d dev # 删除已合并的dev分支
git branch -D dev # 强制删除未合并的dev分支(谨慎使用)
git branch -r # 查看远程分支
git branch -a # 查看所有分支(本地+远程)git checkout dev # 切换到dev分支
git checkout -b feature # 创建并切换到feature分支(等价于git branch feature + git checkout feature)# 用switch的写法:
git switch dev # 切换分支
git switch -c bugfix # 创建并切换到bugfix分支
回退
git reset --soft HEAD~1 # 撤销最近1次提交,保留工作区和暂存区(回到"git add"之后的状态)
git reset --mixed HEAD~1 # 撤销最近1次提交,保留工作区,清空暂存区(默认行为)
git reset --hard HEAD~1 # 撤销最近1次提交,同时清空工作区和暂存区(数据可能丢失,谨慎使用)
git reset --hard <commit-hash> # 重置到指定提交(哈希通过git log查看)git revert HEAD # 撤销最近1次提交(生成新的撤销提交)
git revert <commit-hash> # 撤销指定哈希的提交# 查看某个提交中包含的文件(替换 <commit-hash> 为目标提交哈希)
git ls-tree -r <commit-hash> --name-only
# 从所有提交中移除指定文件(会重写历史)
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch <文件名>" --prune-empty --tag-name-filter cat -- --all# 清理 Git 缓存的旧数据
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# 若之前未推送到远程,直接强制覆盖(谨慎!)
git push origin --force-with-lease --all
合并和变基
git checkout main # 切换到主分支
git merge dev # 将dev分支合并到main分支git checkout feature # 切换到功能分支
git rebase main # 将feature分支基于main分支重新提交(解决冲突后需git rebase --continue)
git rebase -i # 交互式变基,很好用git cherry-pick c1 c2... #可以把多个提交(只要HEAD指向的不是父节点)放在HEAD指向节点下面
查询
git log # 显示完整历史(按时间倒序)
git log --oneline # 简洁显示(一行一个提交,只显示哈希前7位和说明)
git log -n 3 # 只显示最近3次提交
git log --graph # 以图形化方式显示分支合并历史
git log --author="用户名" # 查看指定作者的提交git reflog # 显示所有操作记录(含提交哈希)
符号
HEAD~2^2 # 表示HEAD往上2个节点,然后合并中的第2节点,不加数字默认为1
c1 c2->HEAD~2^2
| |
c3——
|
c4
|
c5->HEADgit tag # 查看所有标签
git tag v1.0 # 为当前提交创建轻量标签
git tag -a v1.0 -m "版本1.0" # 创建带说明的附注标签
git tag -d v1.0 # 删除本地标签
git push origin v1.0 # 推送标签到远程
git push origin --tags # 推送所有本地标签到远程# 另外移动到tag是HEAD移动,不是分支移动过去
.gitignore
-
普通文件名 / 目录名
直接写文件名或目录名,匹配所有同名文件 / 目录。
示例:# 忽略所有名为 "log.txt" 的文件 log.txt# 忽略所有名为 "node_modules" 的目录 node_modules/ # 加斜杠 / 表示仅匹配目录(不加也能匹配,但加/更明确) -
通配符
\*
匹配任意字符(不包含路径分隔符/)。
示例:# 忽略所有 .log 后缀的文件 *.log# 忽略所有以 "temp_" 开头的文件 temp_* -
递归匹配
\**
匹配任意层级的目录(包含路径分隔符/)。
示例:# 忽略所有目录下的 "dist" 文件夹(无论在哪个层级) **/dist/# 忽略 "src" 目录下所有层级的 ".test.js" 文件 src/**/*.test.js -
路径分隔符
/- 放在开头:仅匹配仓库根目录下的文件 / 目录。
- 放在中间:表示目录层级。
示例:
# 只忽略根目录下的 "config.ini",子目录的不忽略 /config.ini# 忽略 "docs" 目录下的 "notes.txt",其他目录的不忽略 docs/notes.txt -
否定规则
!
取消前面定义的忽略规则(即 “例外”),需放在被否定的规则之后。
示例:# 忽略所有 .txt 文件,但保留 "readme.txt" *.txt !readme.txt# 忽略 "build/" 目录,但保留 "build/output/" build/ !build/output/ -
注释
#
以#开头的行是注释,会被 Git 忽略(注意:#不能放在行中间,否则后面的内容会被当作注释)。
示例:# 这是一条注释,不会生效 *.log # 这部分也是注释(仅 *.log 生效) -
转义特殊字符
\
对#、!、*等特殊字符进行转义,使其被当作普通字符处理。
示例:# 忽略名为 "file#1.txt" 的文件(# 需转义) file\#1.txt# 忽略名为 "*.log" 的文件(* 需转义) \*.log
常见示例场景
# 忽略操作系统生成的临时文件
.DS_Store # Mac
Thumbs.db # Windows# 忽略编辑器配置文件
.idea/ # IntelliJ
.vscode/ # VS Code
*.sublime-* # Sublime# 忽略依赖和构建产物
node_modules/ # npm 依赖
dist/ # 打包输出目录
build/ # 构建目录# 忽略日志和缓存
logs/
*.log
.cache/# 忽略环境变量和敏感信息
.env
.env.local
secret.key# 忽略所有 .zip 文件,但保留 "archive.zip"
*.zip
!archive.zip# 只忽略根目录下的 "tmp" 文件夹,子目录的 "tmp" 不忽略
/tmp/
注意事项
-
.gitignore只对未跟踪的文件生效
如果文件已被git add或git commit过,修改.gitignore无法忽略它,需先移除跟踪:git rm --cached 文件名 # 从暂存区移除,保留本地文件 -
优先级
- 项目根目录的
.gitignore对整个仓库生效。 - 子目录的
.gitignore只对当前子目录生效(优先级高于根目录)。 ~/.gitignore_global是全局配置,对所有仓库生效(需通过git config --global core.excludesfile ~/.gitignore_global配置)。
- 项目根目录的
-
空目录
Git 本身不跟踪空目录,若需忽略空目录,可在目录中创建.gitignore文件(内容为空即可)。
