目录
[GNU 工具 for Windows](#GNU 工具 for Windows)
[似乎.gitignore 要git add .gitignore之后才会生效,而且不用进一步commit](#似乎.gitignore 要git add .gitignore之后才会生效,而且不用进一步commit)
[生效的.gitignore哪怕逻辑移除也还是有效,除非物理删除,且物理恢复后继续生效。就像是一旦打开了使用.gitignore的开关,就只要物理存在就有效,不用实际添加进staging area 和 repository,只要存在于working direcotry就行](#生效的.gitignore哪怕逻辑移除也还是有效,除非物理删除,且物理恢复后继续生效。就像是一旦打开了使用.gitignore的开关,就只要物理存在就有效,不用实际添加进staging area 和 repository,只要存在于working direcotry就行)
git commit --amend --no-edit #追加到上一个commit,且不修改信息
git commit -am "your messgae here!" #二段式变为一段式,但要求文件在repository有记录
git clean -fxdn #强力物理删除被忽略的文件,-d删目录,-n预览,-f强力(cached文件不会被清除,因为没有被忽略)
[有的时候git 的匹配机制会考虑ambiguous的问题,如果要让gitbash直接确定是location,用"--",i.e., git log -- /folder/file](#有的时候git 的匹配机制会考虑ambiguous的问题,如果要让gitbash直接确定是location,用“--”,i.e., git log -- /folder/file)
[git reset一定要遵循什么模式出去,什么模式回来的原则,或者无脑选择最彻底的回退方式回来,i.e., --hard!](#git reset一定要遵循什么模式出去,什么模式回来的原则,或者无脑选择最彻底的回退方式回来,i.e., --hard!)
[git reset用于回滚提交,git checkout用于覆盖和切换分支或者切换提交](#git reset用于回滚提交,git checkout用于覆盖和切换分支或者切换提交)
[git branch #在某个commit上创建某个分支,并切换 = git checkout + git checkout -b](#在某个commit上创建某个分支,并切换 = git checkout + git checkout -b)
日志格式

bash
git config --global alias.ls 'log --graph --pretty=format:"\#hash (%h) \#author <%an> \#time <%ar> \#message \"%s\""'

bash
git config --global alias.ls "log --graph --pretty=format:'%C(red)#hash (%h)%Creset %C(yellow)#author <%an>%Creset %C(green)#time <%ar>%Creset %C(cyan)#message \"%s\"%Creset %C(blue)%d%Creset' --abbrev-commit"
GNU 工具 for Windows
Tree
- put the binary exe in the folder of C:\Program Files\Git\usr\bin
2. reboot your gitbash
注意事项
似乎.gitignore 要git add .gitignore之后才会生效,而且不用进一步commit
git rm <file_name> --cached #逻辑上remove
生效的.gitignore哪怕逻辑移除也还是有效,除非物理删除,且物理恢复后继续生效。就像是一旦打开了使用.gitignore的开关,就只要物理存在就有效,不用实际添加进staging area 和 repository,只要存在于working direcotry就行
git commit --amend --no-edit #追加到上一个commit,且不修改信息
git commit -am "your messgae here!" #二段式变为一段式,但要求文件在repository有记录
git clean -fxdn #强力物理删除被忽略的文件,-d删目录,-n预览,-f强力(cached文件不会被清除,因为没有被忽略)
有的时候git 的匹配机制会考虑ambiguous的问题,如果要让gitbash直接确定是location,用"--",i.e., git log -- /folder/file
注意这里暂存区index是文件,主要由blob和路径等信息组成。下表中覆盖指的是不管进度直接覆盖,部分保存指的是不冲突情况下合并,保存是完全不改变不增加不减少;如果出现冲突,则会拒绝执行
checkout有部分保存,reset有保存
命令 暂存区 工作目录 风险等级 checkout <branch>
覆盖 部分保存 中等 reset --soft
✅保存 ✅保存 低 reset --mixed
覆盖 ✅保存 低 reset --hard
覆盖 覆盖 高 checkout --<file>(一般用于解决非文本冲突)
对应发起覆盖 覆盖对应 中等
git reset一定要遵循什么模式出去,什么模式回来的原则,或者无脑选择最彻底的回退方式回来,i.e., --hard!
### **git reset用于回滚提交,git checkout用于覆盖和切换分支或者切换提交** | 维度 | `git reset` | `git checkout` | |------------------|-------------|--------------------| | **主要用途** | 回退提交、撤销更改 | 切换分支、恢复文件 | | **是否移动 `HEAD`** | ✅ 是 | ✅ 是(切换分支时) | | **是否修改 `index`** | ✅ 可控制 | ✅ 可控制 | | **是否修改工作目录** | ✅ 可控制 | ✅ 可控制 | | **是否创建新分支** | ❌ 否 | ✅ `checkout -b` 可以 | | **典型场景** | 撤销提交、取消暂存 | 切分支、丢弃修改 |
### **git checkout -b #创建分支并切换**
### **git branch \<branch_name\> \<commit_hash\> #在某个commit上创建某个分支,并切换 = git checkout \<commit_hash\> + git checkout -b \<branch_name\>**
### **commit拆分相关** | 命令 | 作用 | |-----------------------|------------------------------------------| | `edit` in `rebase -i` | 提供一个"可编辑的历史节点":把原提交的内容恢复到工作区+暂存区,暂停流程 | | `git reset HEAD^` | "炸开"这个提交:退回一个版本,清空暂存区,释放变更到工作目录,便于重新分批提交 | | 区域 | 存什么 | 谁管理 | 是否持久 | |-------------------|-----------------------------|-----|----------------------| | **工作目录** | 你磁盘上的文件(任意状态) | 你 | ✅ 是(文件系统) | | **暂存区(Index)** | 下一次提交的文件快照(准备提交的内容) | Git | ✅ 是(`.git/index` 文件) | | **HEAD / commit** | 历史中的文件快照 + 提交元数据(作者、时间、父提交) | Git | ✅ 是(`.git/objects`) |
### 一旦产生冲突的选择覆盖命令 | 命令 | 作用 | |--------------------------------|-----------------------------------------------| | `git checkout --ours <file>` | 当发生冲突时,使用**当前分支**(our branch)的版本覆盖工作目录中的文件 | | `git checkout --theirs <file>` | 当发生冲突时,使用**被合并分支**(their branch)的版本覆盖工作目录中的文件 |
### 交互式rebase命令变更commit历史 | 操作目标 | 交互式编辑器中的操作 | 具体执行步骤 | 关键命令 / 技巧 | |----------------------|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------| | **修改提交信息** (reword) | 将 `pick` 改为 `reword` | 1. 在 `git rebase -i` 编辑界面中,将目标提交前的 `pick` 改为 `reword` 2. 保存并退出 3. Git 会自动打开编辑器让你修改提交信息 4. 修改后保存即可 | `reword <commit_hash>` → 用于修正拼写、规范格式等 | | **合并多个提交** (squash) | 第一个用 `pick`,后续用 `squash` | 1. 保留第一个提交为 `pick` 2. 将要合并的后续提交改为 `squash` 3. 保存后 Git 会提示你编辑合并后的提交信息 | `squash` = "压缩进上面那个提交" 适合将多个小提交合并为一个逻辑完整的提交 | | **拆解一个提交** (split) | 使用 `edit` | 1. 将目标提交改为 `edit` 2. 保存并退出,Git 暂停 3. 执行:`git reset HEAD^` 4. 此时原提交的文件变为**未暂存状态** 5. 分批 `git add` 并 `git commit`(如:先加 `cat1.html`,提交;再加 `cat2.html`,提交) 6. 最后 `git rebase --continue` | `git reset HEAD^` 是关键: → 回退一次提交 → 覆盖暂存区(清空) → 保留工作目录文件 → 实现"拆解" | | **增加提交** | 使用 `edit` | 1. 将目标提交改为 `edit` 2. 保存后 Git 暂停 3.变更工作文件夹,添加到暂存区,提交即可 | None | | **删除一个提交** (drop) | 使用 `drop` 或删除行 | 1. 将目标提交前的 `pick` 改为 `drop` 或 直接删除该行 2. 保存即可 | `drop <commit_hash>` → 该提交的全部更改将被丢弃 | | **调整提交顺序** (reorder) | 直接交换行顺序 | 1. 在 `rebase -i` 编辑器中,通过剪切/粘贴改变提交的上下顺序 2. 保存即可 | Git 会按新顺序重放提交 注意:确保逻辑依赖合理,避免冲突 |
### 查看远程仓库名
### 关于三个层次的理解 | 层级 | 是否绑定分支 | 说明 | | **1. 工作目录**(Working Directory) | ❌ 不绑定 | 就是你能看到和编辑的文件。Git 允许你在这里自由修改,但它不属于任何分支。 | | **2. 暂存区**(Staging Area / Index) | ❌ 不绑定 | 通过 `git add` 把工作目录的修改"快照"到这里。它是一个中间层,准备下一次提交的内容。它也不属于某个分支。 | | **3. 已提交**(HEAD / Branch) | ✅ 绑定分支 | 只有真正 `git commit` 之后,变更才"固化"到当前分支的历史中,属于该分支。 | |----------------------------------|--------|------------------------------------------------------------| i.e., 无论是工作目录还是暂存区,都是唯一的,公用的,在我们的操作流,基于原状态和操作得到新的状态,是不和分支进行绑定的
### 关于编辑中途能否切换分支的情况讨论 | 情况 | 工作目录状态 | 暂存区状态(是否 `git add`) | 能否切换分支? | 条件说明 | 示例 | |-----|------------------------------|---------------------|------------|---------------------------------------|---------------------------------------------------------------------------| | 1️⃣ | 无修改 | 无变更(干净) | ✅ **可以** | 无任何未提交内容,随时可切 | `git switch main` | | 2️⃣ | 有修改(对应文件未被修改) ⚠️ 未 `git add` | ❌ 未添加 | ✅ **可能可以** | 修改的文件在目标分支中**未被修改**(即与当前分支的共同祖先一致) | `echo "new" >> file.txt` `git switch feature`(若 `feature` 未改 `file.txt`)✅ | | 3️⃣ | 有修改(对应文件已被修改) ⚠️ 未 `git add` | ❌ 未添加 | ❌ **不可以** | 修改的文件在目标分支中**已被修改**(即使未提交),切换会导致覆盖 | `file.txt` 被你改了,`main` 分支也改了 → ❌ | | 4️⃣ | 新增未跟踪文件 ⚠️ 未 `git add` | ❌ 未添加 | ✅ **通常可以** | 新文件在目标分支中不存在,Git 可携带过去 | `echo "data" > new.txt` `git switch main` ✅ | | 5️⃣ | all | ✅ 暂存区发生变更 | ❌ **不可以** | **只要暂存区有内容,Git 默认拒绝切换** (无论目标分支是否有冲突) | `git add file.txt` `git switch main` → ❌ 报错 | | 判断维度 | 说明 | |-----------------------|---------------------------------------------------------------------| | 🔹 **能否切换的核心** | Git 检查:**切换是否会丢失你当前的工作进度或导致内容冲突** | | 🔹 **工作目录修改(未 add)** | ✅ 可携带,**但必须无文件级冲突** | | 🔹 **暂存区有变更(已 add)** | ❌ **一律不允许切换**,无论是否有冲突 | | 🔹 **新文件(untracked)** | ✅ 通常可携带,除非目标分支已有同名文件且被修改 | | 🔹 **安全做法** | 使用 `git stash --include-untracked` 保存所有状态后再切换,最好还是先commit,大不了追加或者回滚 |