git pull实际上没有从远程恢复我的丢失文件

34

我一直在一个分支上工作。 我提交并将其推送到远程存储库。 现在该分支上的某些文件丢失了。 希望它们仍然可以在远程分支上使用,因此我尝试执行 git pull

git pull origin feature/my_branch

然而,Git 表示所有内容都已与远程同步:

 * branch            feature/my_branch -> FETCH_HEAD
Already up-to-date.

怎么才能更新到最新版本呢?我在本地找不到我的丢失文件,因为这些文件缺失导致我的项目编译失败。另外,在Bitbucket的远程分支提交历史记录中,我可以看到那些文件。


它们还在代码库里吗?仅仅因为这些文件仍然存在于远程文件系统中,并不意味着它们存在于代码库中。如果你需要取回这些文件,只需检出一个仍然拥有它们的提交版本,然后重新添加这些文件并提交新的结果即可。 - Alan
嗨,Alan,你所说的“checkout a commit”是什么意思?git log会显示分支上的所有提交记录,我重置到了一个我认为包含文件的提交记录,但实际上并没有吗? - Malloc
你能在回答中详细说明吗?谢谢。 - Malloc
这些文件一开始就被添加到代码库中了吗? - Alan
git reset --hard && git pull - Faishal
1
Git有没有自动发现哪些文件与分支不同步的方法?我一直在运行我的Python文件,逐个发现缺少的文件,然后进行拉取。我也不想覆盖我自己编辑过的文件。 - Charlie Parker
2个回答

35

git pull 对应于先执行 git fetch 然后执行 git merge 的操作。因此,如果您从本地仓库删除文件,则执行 git pull 将不会 恢复它们。

要恢复它们,您需要使用以下命令从远程仓库检出这些文件:

git checkout <branch name> -- <path/to/file>

<branch name> 可以是本地分支或远程分支。

示例:使用远程仓库

  1. 远程上游名称:origin
  2. 远程分支:feature/xpto
  3. 本地分支:feature/xpto
  4. 本地分支缺少的文件:example.js
  5. 从远程分支将文件恢复到本地分支:git checkout origin/feature/xpto -- example.js
  6. 现在你在本地分支上有了example.js

示例2:回滚一个提交

  1. git log
  2. 当前提交哈希:7bb2154cf23b68feb0a0bbbd95446f2cd8bf3a44
  3. 想要回滚到这个提交哈希:dbc04c23b2c6f2dd7bc9b5ef4aef22611a57c3ad
    • git checkout dbc04c23b2c6f2dd7bc9b5ef4aef22611a57c3ad
  4. 只想从上述提交哈希中恢复文件example.js
    • git checkout dbc04c23b2c6f2dd7bc9b5ef4aef22611a57c3ad -- example.js

如果我想获取所有远程分支怎么办? - Malloc
git checkout origin/feature/my_branch 使用最新的提交哈希值创建一个新分支。好的,但是我在远程可以看到的缺失文件在本地没有备份。 - Malloc
我猜你没有看到整个命令,可能错过了命令中的 -- path/to/file 部分。例如:git checkout remote/feature/branch -- example.js 这将从远程分支的根目录获取 example.js 文件。 - Daniel Gomes
嗨,谢谢你的回复。不幸的是,这似乎也不起作用。奇怪的问题。 - Malloc
1
尝试进行简单的测试,将你的远程分支检出到一个新的本地分支:git checkout remote/branch -b local_branch,现在查看一下你的本地系统上是否有这些文件。 - Daniel Gomes
显示剩余8条评论

8
假设你正确描述了问题,@danielcsgomes的方法应该可以正常工作。通过运行git status,您可以找出哪些文件在当前提交中,但不在您的工作目录中。例如(使用 -s 使输出保持简短):
$ rm structy.py
$ git status -s
 D structy.py

获取仅该文件:

$ git checkout -- structy.py

它又回来了。

有时候,只需要切换到其他分支或版本,然后返回到原来的位置,问题就可以解决。例如,在这里最近一次提交到master是添加mp.py,所以如果我这样做:

$ rm mp.py
$ git status -s
 D mp.py
$ git checkout HEAD^
Note: checking out 'HEAD^'.
[verbiage about detached HEAD etc, snipped]
$ git checkout master
Previous HEAD position was 171ce6f... ignore *.log files
Switched to branch 'master'
$ git status -s
$ head -1 mp.py
from multiprocessing import Process, Queue

但这并非总是奏效。对于mp.py来说,它奏效了,因为之前的版本(HEAD^)没有它,而当前版本(master)有它,因此从HEAD^向前移动到master时会恢复该文件。然而,structy.py文件已经存在相当长一段时间了,所以如果我删除它并检出HEAD^或其他分支,它仍然会被从工作目录中删除。因此,像git checkout -- structy.py这样的操作是恢复它的更简单的方法,除非你想使用“很大的锤子”:git reset --hard
如果您确定要放弃所做的任何更改,可以用git reset --hard HEAD。例如,请考虑以下内容:
$ git rm mp.py
rm 'mp.py'
$ git status -s
D  mp.py

(顺便提一下,注意这里的“D”位置不同:我使用了“git rm”,而不仅仅是“rm”,因此我告诉git,如果我提交,mp.py应该在新的提交中被删除,这不仅仅是我误删了。) 然后我决定,不,这是错误的,我希望一切都回到HEAD的状态:

$ git reset --hard HEAD
HEAD is now at 523bacb add multiprocessing example
$ git status -s
$ 

因此,仅在您非常确定的情况下使用reset --hard

Git有没有自动发现哪些文件与分支不同步的方法?我一直在运行我的Python文件,逐个发现缺少的文件,然后进行拉取。我也不想覆盖我自己编辑过的文件。 - Charlie Parker
有时候由于某些神秘的原因,文件并没有完全更新。我发现前往 git 项目的根目录并运行 git checkout <branch-name> . 可以解决这个问题。 - Charlie Parker
@CharlieParker:除了在存储库中进行工作(这是一个相当大的“例外”)之外,Git从来不涉及文件,而是涉及提交。将git pull拆分为两个单独的组件是一个好主意:git fetch和您选择的第二个Git命令。git fetch操作仅涉及提交。第二个操作大多涉及提交,但可能会影响或需要使用您的工作树,即您找到单个文件的地方。 - torek
当涉及到单个文件时,也就是说,当您在 Git 存储库的工作树内实际进行工作时,诸如 git statusgit restoregit checkout <commit> -- <path> 等命令开始发挥作用。我建议人们(为了自己的理智)尽可能将此部分与其他部分分开,其中您一次使用整个提交进行工作(git fetchgit merge 等)。 - torek
@CharlieParker:所以,在这种情况下,使用git status命令:你位于工作树中,并且正在处理该工作树中的文件。git status命令会为你运行两个git diff命令,一个用于比较当前提交(在HEAD中)与Git的索引/暂存区,然后第二个git diff用于比较索引/暂存区与你当前工作树中的文件。如果第一个差异为空(即没有"暂存以提交"的内容),那么第二个差异将准确告诉你在这里想知道的内容。 - torek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接