好奇,假如提交了一个 1G 的文件,然后--amend 修改成一个小文件,最后 git push -f 强制推送,别人从 Github 上拉下来能恢复那个 1G 的文件吗?
1
codehz 2022-01-11 14:43:48 +08:00
1G 的话实际也推不上去(得用 LFS (然后问题就很复杂了))
不考虑这个问题的话,其他人可以通过记录第一次推送时的 commit hash 来强行获取旧的文件(在 github gc 之前都能存在) |
2
maichael 2022-01-11 14:43:51 +08:00
我觉得是可以得,实际上可以反过来想,按照常用的删除历史大文件的文档(比如 https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository ),远不是 --amend 那么简单。
|
3
Explr 2022-01-11 14:45:54 +08:00 2
我在本地测试的结果是能。假定你是说先提交大文件 -> 推送 -> --amend 修改成小文件 -> 强制推送的话。
git 的提交记录是有向无环图,--amend 只是创建一个新结点,新结点的父结点指针指向原提交的父结点。如果把这个局部看成树的话,--amend 提交产生的新结点和原结点是兄弟关系。 而强制推送后,只是强制将 HEAD 指针从原结点指向了新结点,而原结点依旧存在,使用 git checkout <原提交 id>即可检出。但据我测试,如果按照提交大文件 -> --amend 修改成小文件 -> 推送这个顺序进行,git 不会将原结点推送到服务器。这意味着你可以在本地检出原结点,但另一个克隆这个仓库的人不能检出原结点。 |
4
iamzuoxinyu 2022-01-11 14:47:05 +08:00 2
多数情况下可以通过 git reflog 再 checkout 恢复。
|
5
SoloCompany 2022-01-11 15:35:35 +08:00
理论上可以做到禁止
如果在你 force push 之前别人已经 fetch 过那当然无法禁止 其余情况下可以通过在服务器上执行 prune 删掉 dangling object (前提是你可以操作服务器), 或者最彻底的方法是删除 repo 然后重建 至于 github, 这里说的很详细 BTW, 印象中之前好像基于安全或其它原因一直是不允许 git fetch origin <SHA> 的, 但貌似新版的 git 服务器 (2.20.1?) 又允许了 https://stackoverflow.com/questions/14370157/git-fetch-a-specific-commit-by-hash/62463160#62463160 |
6
SoloCompany 2022-01-11 15:36:18 +08:00
|
7
skiy 2022-01-11 17:57:53 +08:00
自己本机有记录的话,应该可以吧? git reflog 获取 commit id 。但是别人那边的话,没实测过。
话说你自己本机也可以测试的啊,测试时不一定要放 1G 的文件。 如果是 *NIX 系统,那直接在 root/USER 就相当于两个用户了。(可以跑 Docker + Git ) |
8
msg7086 2022-01-12 02:55:38 +08:00
主要是看你有没有把对象 push 到服务器。
你可以把 Git 想象成对象存储数据库。你本地写入的数据都会进这个数据库,但是你 push 的时候只会把有效数据 push 到服务器。如果你提交了 1G 的大文件,但是没有把这个文件 push 到服务器,那么服务器的数据库里就不会有这个对象,别人也就无法检出了。反过来说,如果你已经把对象 push 上去了,以后再删除的话也不会从服务器上删除,别人还是可以检出这个文件。 Force push 只是允许你在非 FF 状态下修改分支指针,不会影响数据库里已有的对象。 |