基本概念
工作区:在本地进行文件编辑的实际目录,以在其中自由地创建、修改和删除文件。
暂存区:也称为索引,是一个临时区域,用于存放你准备提交的文件修改。可以将工作区中已修改的文件添加到暂存区,标记这些文件为下次提交的候选对象。
版本库:也叫 Git 仓库,它是 Git 存储项目历史版本的地方。版本库包含了所有的提交记录、分支信息以及文件的不同版本等。
基本的 Git 工作流程如下:
- 在工作区中修改文件。
- 将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区。
- 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。
Git 有三种状态,你的文件可能处于其中之一: 已提交(committed) 、已修改(modified) 和 已暂存(staged) 。
- 已修改表示修改了文件,但还没保存到数据库中。
- 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
- 已提交表示数据已经安全地保存在本地数据库中。
远程仓库相关操作
git shortlog -sn # 获取当前仓库的所有提交者
git shortlog -sne # 获取当前仓库的所有邮箱
git remote -v # 查看远程仓库信息
git clone [远程仓库地址] # 克隆远程线上项目到本地
git add remote origin [远程仓库地址] # 本地仓库与远程仓库建立连接
修改本地仓库中关联的远程仓库的URL地址
# 删除关联的远程仓库地址
git remote remove origin
# 添加新的远程仓库地址
git remote add origin 远程仓库地址
将文本修改的文件推送到远程仓库步骤
# 1、将本地文件存在暂存区
git add *
git add [filename]
# 2、提交
git commit - m "提交信息说明"
# 3、推送至远程仓库
git push
本地创建分支并推送至远程
# 1、新建并切换新分支
git branch 分支名称 # 新建分支
git checkout 分支名称 # 切换至新分支
# or 使用一条命令创建分支并切换至新分支
git checkout -b 分支名称
# 2、将新分支推送至远程
git push -u origin 分支名称
# 如果使用git push会报错,需要将本地分支与远程仓库建立联系
git push --set-upstream origin 分支名称
-u 参数用于设置上游(tracking)关系,这样以后就可以简单地使用 git push 和 git pull 而不需要指定分支名。
版本回退
git reset (移动HEAD,版本会被丢弃)
git reset 是退回到某个本地版本,也就是将HEAD 指针往回移动到我们想要的并且是之前存在的版本,但是HEAD指针移动到该版本之后,该版本后面提交的版本会被弃掉,只能在该版本之上重新修改并提交。
graph LR
版本1[版本1] --> 版本2[版本2] --> 版本3[版本3]
git reset [--soft | --mixed | --hard] [HEAD]
另外git reset --hard HEAD^ 等价于git reset --hard xxx(xxx为commit id)
git reset 的本质是移动当前分支的 HEAD 指针,并可选地修改暂存区(index)和工作区(working directory)的文件状态。
--mixed重置 HEAD + 暂存区(工作区保留)。默认模式,撤销git add或回退提交但保留本地修改--soft仅重置 HEAD(暂存区、工作区都保留)。场景有:合并多个提交,或撤销提交但保留修改(可重新提交)--hard重置 HEAD + 暂存区 + 工作区(会丢失未提交的修改)。场景有:彻底回退到某个版本,放弃所有本地修改
git revert (有新提交,保留所有版本)
git revert是生成一个新的版本提交来撤销某个以前版本的提交,相当于一次逆向的提交“中和”想要撤销的版本的提交,这意味着在这个 新的提交版本 到 要撤销的版本 的所有版本(若有)都会被保留,不会像git reset那样回退某个版本之后该版本之后的所有提交的版本都被弃掉,而且这个要被撤销的旧版本也不会从版本库中移除,这样做的好处是防止了项目丢失历史。
graph LR
版本1 --> 版本2 --> 版本3
git revert [选项] <commit-id>
git revert [选项] <提交范围/提交ID>
合并代码
将 dev 分支代码合并到 master 分支
# 确保 master分支到代码是最新的
git checkout master
git pull origin master
# 切换到 dev 分支,确保 dev 分支到代码是最新的
git checkout dev
git pull origin dev
# 切换到 master 分支
git checkout master
git merge dev
git switch master # 切换到master分支(如果你使用的是Git 2.23及以上版本)
git merge dev --no-ff -m "Merge branch 'dev' into master" # 执行合并并创建一个新的合并提交(非快速向前)
git push origin master # 推送更改到远程仓库的master分支
如果 merge 之后想取消,不合并了。
执行了 git merge ,但未执行 git push
git merge --abort
将 dev 分支某一次提交 commit 合并到 master
# dev 分支
git pull # 拉取最新代码
git checkout master # 切换分支到master
# master分支
git cherry-pick commit-id # 执行将某个commit合并到master
# 若遇到冲突,需手动解决冲突,执行以下命令
git cherry-pick --continue
# 执行上述命令后 之后按提交、推送流程执行命令
若想在执行git cherry-pick commit-id 命令后直接取消,不合并了,可执行命令
git cherry-pick --abort
提交 commit
提交是将暂存区中的文件快照永久保存到版本库的操作。每次提交都会生成一个唯一的哈希值(也称为提交哈希),用于标识该次提交。提交时需要添加提交信息,以描述本次提交所做的更改,方便后续查看和追溯。
获取最新一次 commit 的指定信息
# 获取最新一次 commit 的 author_email
git log -1 --pretty=format:'%ae'
# 获取最新一次 commit 的 author_name
git log -1 --pretty=format:'%an'
# 获取最新一次 commit 的 branch
git rev-parse --abbrev-ref HEAD
# 获取最新一次 commit 的 commit-id
git rev-parse --short HEAD # 返回 commit-id 前 7 位
git rev-parse HEAD #返回完整的 commit-id
修改最新一次提交(commit)的信息
第一种情况:(执行 commit,未执行 push)
- 确保工作区干净 先确认当前工作区没有未提交的修改(可通过
git status检查)。如果有未提交的修改,git commit --amend会将这些修改一起包含到最新的 commit 中(如需仅修改信息,可先git stash暂存修改,完成后git stash pop恢复)。 - 执行修改命令运行以下命令:
git commit --amend
git commit --amend 命令仅适用于最新一次 commit,若需修改更早的提交,需使用 git rebase -i 进行交互式变基。
第二种:(执行 commit 后,也 执行 push 操作)
如果最新的 commit 已经推送到远程仓库(如 GitHub/GitLab),修改本地信息后,需要强制推送才能同步到远程(谨慎操作,避免覆盖他人提交):
# 推荐:更安全的强制推送,会检查远程是否有新提交
git push --force-with-lease origin <分支名>
# 或(不推荐,可能覆盖他人修改)
git push -f origin <分支名>
仅删除某一次 commit 但未 push 的代码
# 第一种: 删除最近一次 commit
# 查看提交历史,找到你想要删除的提交的前一个提交的哈希值
git log
# 假设要删除的提交的前一个提交哈希值是 abc123
# 仅移动 HEAD 指针,保留工作区和暂存区的更改
git reset abc123
# 或者,移动 HEAD 指针并清空暂存区,但保留工作区的更改
git reset --soft abc123
# 又或者,移动 HEAD 指针,清空暂存区和工作区的更改
git reset --hard abc123
# 第二种 删除非最近一次 commit
# 查看提交历史,找到你想要删除的提交的前一个提交的哈希值
git log
# 假设要删除的提交的前一个提交哈希值是 abc123
git rebase -i abc123
执行上述命令后,会打开一个文本编辑器,显示从指定提交开始到当前提交的所有提交记录,格式如下:
pick xyz456 Commit message 1
pick def789 Commit message 2
pick ghi012 Commit message 3
找到要删除的提交,将其前面的 pick 改为 drop 或者直接删除该行,然后保存并退出编辑器。Git 会按照新的提交顺序重新应用提交,从而删除指定的提交。
暂存 stash
git stash 命令,是 Git 中用于临时保存工作区 / 暂存区未提交的改动的核心命令 —— 当你需要切换分支、拉取代码或回滚,但又不想提交当前未完成的改动时,git stash 可以把这些改动「暂存」起来,待后续恢复,避免改动丢失或污染分支。
- 工作区改动:未执行
git add的修改; - 暂存区改动:已执行
git add但未git commit的修改; - stash 栈:Git 会把每次
stash的改动按「后进先出」的栈结构存储,可多次 stash 并按需恢复。
保存当前改动(git stash / git stash push)
这是最基础的用法,把工作区 + 暂存区的未提交改动保存到 stash 栈,同时清空工作区 / 暂存区的改动(回到最近一次提交的干净状态)。
# 最简写法(等价于 git stash push)
git stash
# 推荐:添加备注(便于区分多个 stash)
git stash push -m "修复登录bug:未完成"
# 只保存工作区改动(忽略暂存区)
git stash push --keep-index
# 只保存指定文件的改动
git stash push src/login.js -m "只保存登录文件改动"
查看 stash 列表(git stash list)
查看所有已保存的 stash 记录,每条记录有唯一标识(stash@{n},n 从 0 开始,0 是最新的)。
git stash list
# 输出示例:
# stash@{0}: On main: 修复登录bug:未完成
# stash@{1}: On dev: 新增支付功能:未完成
# stash@{2}: On main: 调整样式:未完成
恢复 stash 改动(git stash apply / pop)
把 stash 中的改动恢复到当前工作区,两种方式的核心区别是「是否删除 stash 记录」
# 方式1:恢复最新的 stash(stash@{0}),且保留 stash 记录(可多次恢复)
git stash apply
# 方式2:恢复指定的 stash(比如 stash@{1})
git stash apply stash@{1}
# 方式3:恢复最新的 stash,并从栈中删除该记录(推荐,避免栈堆积)
git stash pop
# 方式4:恢复指定的 stash 并删除
git stash pop stash@{1}
分支管理
本地创建并切换至新分支
# 旧语法
git branch <branch-name> # 创建新分支
git checkout <branch-name> # 切换分支
# 简写
git checkout -b <branch-name> # 新建并切换新分支
# 新写法(语义清晰) 从 Git 2.23 版本后,可以使用
git switch <branch-name> # 切换分支
git switch -c <branch-name> # 创建并切换分支
# 将本地分支推送至远程仓库
git push -u origin <branch-name>
# 本地分支与远程分支建立联系
git push --set-upstream origin <branch-name>
如何删除 Git 中的分支?
# 删除本地分支
git branch -d <branch-name>
# 强制删除分支(包括未合并的更改)
git branch -D <branch-name>
# 删除远程分支
git push origin --delete <branch-name>
tag 管理
git tag [tag_name] # 创建 tag
git push <remote> <tag_name> # 推送某个标签到远程仓库
git push <remote> --tags # 推送所有标签到远程仓库
# 若确认要覆盖远程标签(谨慎!会替换远程已有标签)
git push origin --force [tag_name]
git tag -d [tag_name] # 删除本地标签
git push origin --delete [tag_name] # 将删除的标签推送至远程仓库
# 查看所有 tag
git tag
其他 git 命令
git diff 文件对比
git diff # 对比工作区与暂存区
git diff --cached # 对比暂存区与版本库
git diff --staged # 对比暂存区与版本库
# 对比不同 commit
git diff <commit-id1> <commit-id2>
# 对比两个分支的差异(比如 main 和 feature 分支)
git diff main feature
git apply 应用补丁文件
git apply 命令,是 Git 中用于直接应用补丁文件(patch)到工作区的底层命令,核心作用是「将代码差异(patch)应用到当前仓库,而不创建提交记录」。
- 补丁文件(patch) :记录文件差异的文本文件(可通过
git diff/git format-patch生成) - 应用场景:需要把 A 仓库的代码修改(比如一个 bug 修复)传递到 B 仓库,但两个仓库无关联(无共同提交历史),或 B 仓库不是 Git 仓库(仅本地目录)
- 操作逻辑:在 A 仓库用
git diff生成补丁 → 复制补丁文件到 B 仓库 → 用git apply应用修改
# 生成工作区未提交改动的 patch(保存到 diff.patch)
git diff > diff.patch
# 应用 patch 文件到工作区
git apply diff.patch
git rev-parse 获取 commit hash
# 输出当前 HEAD 对应的完整 commit hash(40位)
git rev-parse HEAD
# 输出示例:a1b2c3d4e5f67890abcdef1234567890abcdef12
# 输出简短 commit hash(默认7位)
git rev-parse --short HEAD
# 输出示例:a1b2c3d
# 解析分支名到 commit hash
git rev-parse main # 输出 main 分支最新提交的 hash
git rev-parse dev # 输出 dev 分支最新提交的 hash
git ls-files 文件追踪
# 列出当前目录及子目录下被跟踪的文件(相对路径)
git ls-files
# 列出暂存区中的文件
git ls-files --cached
# 列出未被跟踪的文件
git ls-files --others
# 列出被忽略的文件
git ls-files --ignored
git 配置
设置 / 查看 git 信息
$ git config --global user.name "xxx" # 用户名
$ git config --global user.email "xxx@example.com" #填你自己的邮箱
# 查看配置信息
git config --list
git config user.name # 查看用户名称
git config user.email # 查看邮箱
# 配置 Git 钩子脚本的存放目录
git config core.hooksPath [目录名称]
Git 钩子是一些自动化脚本(如 pre-commit、commit-msg、pre-push 等),Git 在执行特定操作(如 commit、push)时会自动触发这些脚本。
- 默认路径:Git 钩子脚本默认存放在仓库的
.git/hooks目录下(比如your-project/.git/hooks)。 - 关键问题:
.git目录是 Git 的私有目录,不会被提交到版本库,所以默认的.git/hooks里的钩子脚本无法在团队间同步。
创建 SSH Key
# 创建 SSH Key
$ ssh-keygen -t rsa -C "xxxemail@example.com(自己的邮箱地址)"
其他
git 安装教程:git-scm.com/book/zh/v2/…