git使用场景常见问题解决

git使用场景常见问题解决

spiritTrance Lv3

git stash pop 到错误的分支

使用场景:你有两个分支maindev,你在dev的修改临时使用了git stash暂存,之后切换到了main分支,然后使用了git stash pop,之后提示要merge

解决方案:首先使用git reset --hard HEAD取消git stash pop对暂存区的修改。这里需要注意的是,如果git stash pop对暂存区造成了conflict需要merge的时候,stash的记录是不会真正弹出来的。因此,之后直接git checkout dev之后,使用git stash pop即可安全恢复。

git commit 之后发现不小心加入了不该加入的文件

如果没有提交到远程仓库:

1
2
3
git reset --soft HEAD~1     # 回退到上一个版本,保留工作区和暂存区的代码
git reset HEAD your/unwanted/file.txt # 取消暂存区的文件
git rm --cached your/unwanted/file.txt # 取消追踪文件的更改记录

之后,记得修改.gitignore文件。

这里详细解释一下git resetgit rm --cached的区别:前者只是把修改从暂存区移除,但是git仍然在跟踪对应文件;后者表示把修改从暂存区移除,并且git不再跟踪指定文件的修改。之后,在.gitignore里面加入指定文件,之后加入git add .的时候,也不会误加入。

如何表明 git 在跟踪?使用 git commit -m "message",可以看到 git 会提示哪些文件做了修改。你用 git add targetfile.txt之后,就会把对应文件从工作区加入暂存区。但是你如果使用了git rm --cached targetfile.txt之后,即使对应文件有修改,commit的时候也不会提示这个文件做了修改。

如果提交到了远程仓库:

1
2
git revert HEAD             # 撤销
git push

这里介绍一下git revert <ver>

  • 如果工作区是干净的,那么撤销操作会根据你在HEAD产生的操作,生成一个逆向操作,同时作用于工作区和暂存区,之后会要求你写一个提交信息,之后会自动提交撤销操作。
  • 如果工作区有新的修改,会要求你提交你在工作区新增的修改。之后使用revert的时候,会根据你在<ver>的修改,生成一个反向操作。但如果你在后续的提交过程中,和生成的反向操作产生冲突,则需要你手动解决冲突,之后使用git add confilct_file,然后执行git revert --continue。如果想撤销revert操作,则可以使用git revert --abort.
  • 如果需要撤销范围内操作,需要执行:git revert --no-commit a1b2c3d^..HEAD,最后再commit一下。提交之前,可以利用git status查看一下状态。

git 仓库下面有其他的 git 仓库,并且其他的 git 仓库是从其他平台(如github)上 clone 下来的

TODO

希望从 git 的所有历史记录中抹除密钥的存在

因为需要重写整个历史记录,因此这是个十分麻烦且危险的操作。在执行之前,需要通知所有协作者。需要使用git-filter-repo。在执行之前,需要备份整个仓库。

下面这些指令用于抹除敏感字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 推荐使用 Python3
python3 -m pip install --user git-filter-repo
# 为你的项目创建一个裸克隆
git clone --bare https://github.com/your-org/your-repo.git
# 进入这个新创建的裸仓库目录
cd your-repo.git
cat expressions.txt
### expressions.txt里面的内容
### AKIAIOSFODNN7EXAMPLE
### my-super-secret-password
### BEGIN RSA PRIVATE KEY
# --replace-text 后面跟着你的敏感信息文件
git-filter-repo --replace-text expressions.txt # 会遍历所有版本,将找到的字符串替换为***removed***
# --force 参数会用你本地的历史覆盖远程历史
git push origin --force --all
git push origin --force --tags

下面这些指令用于抹除某个文件:

1
2
3
4
5
6
7
8
9
# 为你的项目创建一个裸克隆(只包含 Git 数据,没有工作区)
git clone --bare https://github.com/your-org/your-repo.git
# 进入这个新创建的裸仓库目录
cd your-repo.git
# 将 'path/to/your/unwanted-file.txt' 替换成你要删除的文件的真实路径
git-filter-repo --path path/to/your/unwanted-file.txt --invert-paths
# --force 参数会用你本地的历史覆盖远程历史
git push origin --force --all
git push origin --force --tags

或者使用filter-branch命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 这个命令会遍历所有分支和标签,从索引中移除指定文件
# --ignore-unmatch 确保在没有该文件的提交中不会报错
# --prune-empty 会移除因删除文件而变为空的提交
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch 'path/to/your/unwanted-file.txt'" \
--prune-empty --tag-name-filter cat -- --all

# 清理 Git 留下的原始引用的备份
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin

# 执行垃圾回收,彻底删除悬空的对象
git reflog expire --expire=now --all
git gc --prune=now --aggressive

# 最后,强制推送到远程
git push origin --force --all
git push origin --force --tags

  • Title: git使用场景常见问题解决
  • Author: spiritTrance
  • Created at : 2025-08-06 11:51:09
  • Updated at : 2025-08-06 15:29:24
  • Link: https://spirittrance.github.io/2025/08/06/git_scene/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments