git 学习笔记
git 基础
工作区:在本地磁盘上看到、正在编辑的文件,Git 不会自动记录这里的修改
暂存区:存放的是:下一次 commit 要包含的内容,git add 的文件会放入暂存区
本地仓库:git commit 后,文件会放入本地仓库
1 | 工作区 -- git add --> 暂存区 -- git commit --> 本地仓库 |
git 文件状态
Untracked:文件存在于工作区,Git 从未记录过它,不在暂存区,也不在仓库中
Tracked:文件 add 后,属于 Tracked
Unmodified:文件已被 Git 跟踪,工作区内容 == 最近一次 commit
Modified:文件已被跟踪,工作区内容 ≠ 暂存区
Staged:文件已放入暂存区
git stash
git stash 是 Git 中的一个命令,用来临时保存当前工作目录和暂存区的修改(即未提交的更改),以便可以切换到其他分支或执行其他操作,而不会丢失当前的工作进度。
在 main 分支上写了一些代码,还没提交,这时需要切到 dev 分支修一个 bug,但当前的修改又不能提交,这时可以:
1 | git stash |
修完 bug 之后回到原来的分支,并恢复之前的修改:
1 | git switch main |
| 命令 | 作用 |
|---|---|
git stash |
将当前修改保存到 stash 栈中,并恢复到干净状态 |
git stash list |
查看所有的 stash 记录 |
git stash pop |
弹出最近的 stash,并应用到当前工作区 |
git stash apply |
应用某个 stash(不会删除 stash 记录) |
git stash drop |
删除某个 stash |
git stash clear |
清空所有 stash |
stash会保存:工作区和暂存区的修改。- 新增的未被
git add的文件(即“未跟踪文件”),默认不会被 stash;要连这些一起保存可以加u:
1 | git stash -u # 包括 untracked 文件 |
squash
把多个 Git 提交合并成一个提交(commit), 通过 git rebase 等操作实现的。
假设想把最近的 3 次提交合并成 1 次提交:
1 | git rebase -i HEAD~3 |
这时 Git 会打开编辑器,显示如下内容:
1 | pick 123abc First commit |
把后面的改成 squash 或 s:
1 | pick 123abc First commit |
保存后,Git 会提示编辑新的提交信息(可以合并、重写)
原来是:
1 | commit 789ghi Third commit |
现在变成:
1 | commit abcd999 Combine all three commits |
git rebase
git rebase 就是把当前分支的提交,重新“搬到”另一个分支的最新状态之后。
| 操作 | 原理 | 提交历史 | 是否创建新 commit |
|---|---|---|---|
merge |
把两个分支合并在一起 | 产生“合并节点”,保留分支历史 | 创建一个合并 commit |
rebase |
把你的提交挪到目标分支之后 | 更线性,更干净 | 会重写历史(新 hash) |
假设有如下分支结构:
1 | A---B---C (main) |
执行:
1 | git checkout feature |
会变成:
1 | A---B---C---D'---E'---F' (feature) |
D E F 的内容没变,但它们的 hash 值变了, 所以是新提交(D’ E’ F’)
git fetch
git fetch 是 Git 中的一个命令,用来从远程仓库获取最新的提交记录,但不会自动合并到当前分支。
1 | git fetch origin |
- 联系远程仓库
origin - 下载所有新的分支、标签、提交等
- 把它们存储到本地的远程分支,如:
origin/main、origin/dev - 不会改变当前工作分支(比如 main)
假设本地在 main 分支上,远程的 origin/main 提前更新了两个提交:
1 | 远程:A---B---C---D (origin/main) |
执行:
1 | git fetch origin |
之后的本地 Git 仓库会知道远程有个新提交 D,但当前分支不会自动合并这个提交:
1 | A---B---C (main) |
git pull
实际上是两个操作的组合:
1 | git fetch + git merge |
git push
git push 中的 -u(或 --set-upstream)参数的作用是:
将当前本地分支与远程分支绑定(设置默认上游分支),以后可以直接用 git push 或 git pull,不需要每次都指定远程分支。
第一次创建并切换一个新分支:
1 | git checkout -b feature/login |
然后把这个分支推到远程:
1 | git push -u origin feature/login |
以后只需要:
1 | git push # 推送当前分支 |
不用每次都写全命令。
amend
修改提交信息:
1 | git commit --amend |
忘了加文件?补上再 amend:
1 | git add filename # 把漏加的文件加入暂存区 |
这样不会生成一个新提交,而是把上一次提交修改为包含新的内容。
1 | git commit -m "Fix typo" |
后来发现还有一个文件漏加了:
1 | git add forgot.js |
现在 Fix typo 这个提交会变成包含两个文件的提交。
git commit --amend 会 重写提交历史,也就是修改了原来的 commit(commit hash 会改变)
git cherry-pick
假设在 feature-a 分支修了一个 bug,但现在也希望 main 分支也拥有这个修复,不想合并整个 feature-a,只想拿那一个修复 commit → 用 cherry-pick
在 feature 分支有一个提交 abc123
切回 main 分支:
1 | git checkout main |
main 分支现在就拥有了 abc123 这个提交(内容一样,但 hash 不一样)
多个 commit:
1 | git cherry-pick hash1 hash2 hash3 |
cherry-pick 会创建一个 全新的 commit,虽然内容一样,但 hash 会变