From 7f6f3d7a00c0cfdc0c0db22727639d501474902f Mon Sep 17 00:00:00 2001 From: zihluwang Date: Thu, 20 Aug 2026 15:09:25 +0800 Subject: [PATCH] docs(blogs): add git usage cheatsheet - Cover git update-index --skip-worktree for ignoring local changes to tracked files - Include stashing, amending, undo, reflog, bisect, log, clean and cherry-pick tips - Add matching zh-hans and en-gb versions --- docs/en-gb/blogs/git-cheatsheet.md | 161 +++++++++++++++++++++++++++ docs/zh-hans/blogs/git-cheatsheet.md | 161 +++++++++++++++++++++++++++ 2 files changed, 322 insertions(+) create mode 100644 docs/en-gb/blogs/git-cheatsheet.md create mode 100644 docs/zh-hans/blogs/git-cheatsheet.md diff --git a/docs/en-gb/blogs/git-cheatsheet.md b/docs/en-gb/blogs/git-cheatsheet.md new file mode 100644 index 0000000..24bd78e --- /dev/null +++ b/docs/en-gb/blogs/git-cheatsheet.md @@ -0,0 +1,161 @@ +--- +title: Git Cheatsheet +tags: + - git + - tips +author: + name: Zihlu Wang + email: real@zihluwang.me +--- + +## Ignoring Local Modifications to Tracked Files: `git update-index --skip-worktree` + +When you need to modify a Git-tracked file locally but don't want those changes to show up in `git status` or in commits (e.g. a local `application-local.yml`, `.env`, or IDE configuration), you can use `--skip-worktree` to make Git ignore local modifications to that file. + +### Marking and Unmarking + +```bash +# Make Git ignore local modifications to the file +git update-index --skip-worktree + +# Unmark the file and track it again +git update-index --no-skip-worktree +``` + +### Listing Ignored Files + +Marked files are shown with an `S` flag in `git ls-files -v`: + +```bash +git ls-files -v | grep '^S' +``` + +### Committing Changes to a Marked File + +To commit new changes to the file, unmark it first, commit, then mark it again: + +```bash +git update-index --no-skip-worktree +git add +git commit -m "chore: update config" +git update-index --skip-worktree +``` + +### `--skip-worktree` vs `--assume-unchanged` + +Both options stop Git from reporting modifications to tracked files, but they serve different purposes: + +| Option | Purpose | +| -------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `--assume-unchanged` | A performance optimisation for large files that rarely change; Git may re-track the file once it notices a change | +| `--skip-worktree` | Deliberately ignore local changes for "keep local modifications, don't commit" scenarios; more persistent | + +So for "ignoring local changes", use `--skip-worktree`. + +### Caveats + +- `--skip-worktree` only affects the working tree — it is not a permanent ignore. Operations that rewrite the file, such as `git pull`, `git checkout`, or `git stash`, may overwrite your local changes or cause a conflict. If the file is also likely to change upstream, unmark it before pulling. +- It only applies to **tracked** files; for untracked files, use `.gitignore`. + +## Stashing Unfinished Work: `git stash` + +When you need to switch branches mid-task, use `git stash` to set your working-tree changes aside: + +```bash +git stash push -m "work in progress" # save with a message +git stash -u # include untracked files +git stash list # list saved stashes +git stash pop # restore and drop the stash +git stash apply # restore but keep the stash +git stash drop # delete a stash +``` + +## Amending the Latest Commit: `git commit --amend` + +When you commit and then realise you forgot a file or want to change the message: + +```bash +git add +git commit --amend # keep the same message, fold in new changes +git commit --amend -m "new message" # also change the message +``` + +Note: if the commit has already been pushed, prefer adding a new commit instead of rewriting shared history. + +## Undoing Changes: `git restore` and `git reset` + +```bash +git restore # discard unstaged working-tree changes +git restore --staged # unstage but keep the changes (like git reset HEAD ) +git restore --source=HEAD # restore the file to its HEAD version +``` + +To discard all uncommitted changes (including the staging area): + +```bash +git reset --hard HEAD +``` + +`--hard` also resets the working tree, so double-check that nothing you want to keep would be lost. + +## Recovering Lost Commits: `git reflog` + +When a commit seems to have vanished after a bad `git reset --hard` or `git rebase`, `reflog` records every place HEAD has been: + +```bash +git reflog +git reset --hard HEAD@{2} # go back to an earlier recorded position +``` + +As long as the commit still exists in the object database, reflog can get you back to it. + +## Bisecting a Regression: `git bisect` + +When you don't know which commit introduced a bug, `git bisect` uses binary search to locate it: + +```bash +git bisect start +git bisect bad # the current commit is bad +git bisect good # mark a known-good commit +``` + +Git checks out a midpoint commit; you just mark each as `good` or `bad` until it narrows down the offending commit: + +```bash +git bisect good # or git bisect bad +git bisect reset # finish and return to your branch +``` + +## Friendlier History: `git log` + +```bash +git log --oneline --graph --decorate --all # graph view across all branches +git log -S "some-string" --all # find commits that added/removed a string +git blame # show the last modifier of each line +git blame -L 10,20 # restrict to a line range +``` + +## Cleaning Up Untracked Files: `git clean` + +```bash +git clean -n -fd # preview which files would be removed (always run this first) +git clean -fd # delete untracked files and directories +``` + +`-n` only shows what would be deleted without deleting it — preview before you execute. + +## Picking Commits: `git cherry-pick` + +Apply a specific commit from another branch onto your current branch: + +```bash +git cherry-pick +``` + +## Deleting Merged Local Branches + +```bash +git branch --merged | grep -v '\*' | xargs -n 1 git branch -d +``` + +This deletes all local branches merged into the current branch (except the current one). Preview with `git branch --merged` first. diff --git a/docs/zh-hans/blogs/git-cheatsheet.md b/docs/zh-hans/blogs/git-cheatsheet.md new file mode 100644 index 0000000..9f5770b --- /dev/null +++ b/docs/zh-hans/blogs/git-cheatsheet.md @@ -0,0 +1,161 @@ +--- +title: Git 使用小贴士 +tags: + - git + - tips +author: + name: Zihlu Wang + email: real@zihluwang.me +--- + +## 忽略已跟踪文件的本地改动:`git update-index --skip-worktree` + +当你需要在本机修改某个已被 Git 跟踪的文件,但又不希望这些改动出现在 `git status` 或提交里时(比如本地的 `application-local.yml`、`.env`、IDE 配置等),可以使用 `--skip-worktree` 让 Git 忽略该文件的本地改动。 + +### 标记与取消标记 + +```bash +# 让 Git 忽略该文件的本地改动 +git update-index --skip-worktree + +# 取消忽略,恢复对该文件的跟踪 +git update-index --no-skip-worktree +``` + +### 查看所有被忽略的文件 + +被标记的文件会在 `git ls-files -v` 的输出中以 `S` 标识: + +```bash +git ls-files -v | grep '^S' +``` + +### 提交对已标记文件的改动 + +如果需要向仓库提交该文件的新改动,需要先取消标记、提交、再重新标记: + +```bash +git update-index --no-skip-worktree +git add +git commit -m "chore: update config" +git update-index --skip-worktree +``` + +### `--skip-worktree` 与 `--assume-unchanged` 的区别 + +两个选项都能让 Git 不再关注已跟踪文件的改动,但用途不同: + +| 选项 | 用途 | +| -------------------- | ---------------------------------------------------------------------------- | +| `--assume-unchanged` | 性能优化,适用于几乎不会改变的大型文件;Git 检测到文件变化后可能自动重新跟踪 | +| `--skip-worktree` | 有意忽略本地改动,适用于「保持本地修改但不上传」的场景,更持久 | + +因此,「忽略本地改动」应该使用 `--skip-worktree`。 + +### 注意事项 + +- `--skip-worktree` 只影响工作区层面,并不是一个「永久忽略」。在执行 `git pull`、`git checkout`、`git stash` 等可能改写该文件的操作时,本地改动可能会被覆盖或引发冲突。如果该文件在远端也会变化,建议在拉取前先取消标记。 +- 它只对**已跟踪**的文件生效;对于未跟踪的文件,请使用 `.gitignore`。 + +## 暂存未完成的改动:`git stash` + +需要临时切换分支时,可以用 `git stash` 把工作区改动保存起来: + +```bash +git stash push -m "work in progress" # 保存并附带备注 +git stash -u # 连同未跟踪的文件一起保存 +git stash list # 查看已保存的改动 +git stash pop # 恢复并删除该条记录 +git stash apply # 恢复但保留该条记录 +git stash drop # 删除某条记录 +``` + +## 修正最近一次提交:`git commit --amend` + +当你提交后发现忘了加入某些文件、或想修改提交信息时: + +```bash +git add +git commit --amend # 保持原提交信息,合并进新改动 +git commit --amend -m "新提交信息" # 同时修改提交信息 +``` + +注意:如果该提交已经被推送到远端,请改用新增一个提交的方式,避免改写公共历史。 + +## 撤销改动:`git restore` 与 `git reset` + +```bash +git restore # 丢弃工作区(未暂存)的改动 +git restore --staged # 取消暂存,保留改动(相当于 git reset HEAD ) +git restore --source=HEAD # 将文件恢复到 HEAD 版本 +``` + +想彻底丢弃未提交的全部改动(包括暂存区),可以: + +```bash +git reset --hard HEAD +``` + +`--hard` 会连同工作区一并重置,使用前请确认没有需要保留的改动。 + +## 找回丢失的提交:`git reflog` + +误用了 `git reset --hard` 或 `git rebase` 导致提交「消失」时,`reflog` 记录了 HEAD 的所有历史位置: + +```bash +git reflog +git reset --hard HEAD@{2} # 回到 reflog 中记录的某个位置 +``` + +只要提交还在对象库中,就能通过 reflog 找回。 + +## 二分查找回归:`git bisect` + +当某个 bug 不知道从哪个提交引入时,`git bisect` 会通过二分法帮你定位: + +```bash +git bisect start +git bisect bad # 当前提交是有问题的 +git bisect good # 标记一个已知正常的提交 +``` + +Git 会不断切换到一个中间提交,你只需要根据当前状态标记 `good` 或 `bad`,最终会定位到引入 bug 的那个提交: + +```bash +git bisect good # 或 git bisect bad +git bisect reset # 结束并回到原分支 +``` + +## 更友好的历史记录:`git log` + +```bash +git log --oneline --graph --decorate --all # 以图形方式查看全部分支 +git log -S "some-string" --all # 查找新增或删除某字符串的提交 +git blame # 查看每行代码的最后修改者 +git blame -L 10,20 # 只查看指定行范围 +``` + +## 清理未跟踪文件:`git clean` + +```bash +git clean -n -fd # 先预览会被删除的文件(安全起见务必先跑) +git clean -fd # 删除未跟踪的文件和目录 +``` + +`-n` 表示只展示而不实际删除,建议先预览再执行。 + +## 精挑细选:`git cherry-pick` + +把其他分支上的某个提交应用到当前分支: + +```bash +git cherry-pick +``` + +## 清理已合并的本地分支 + +```bash +git branch --merged | grep -v '\*' | xargs -n 1 git branch -d +``` + +该命令会删除所有已合并进当前分支的本地分支(当前分支除外)。执行前建议先用 `git branch --merged` 预览。