如何强制执行 "git pull" 并覆盖本地文件?

9510

如何在执行 git pull 命令时强制覆盖本地文件?我的本地仓库中包含与服务器上相同文件名的文件。

错误:无法完成合并,未跟踪的工作树文件 'example.txt' 将被覆盖。


48
如果您正在阅读此内容并认为自己可能会丢失文件,我曾经遇到这种情况,并发现Sublime Text的缓冲区保存了我的工作 - 如果我在某个项目上工作时,意外删除了所有内容,尝试解决类似于这个问题或使用此问题的答案,并且已经在Sublime中打开这些文件(有很大的可能性),那么文件仍将存在于Sublime中,可能是在其中,也可能在撤销历史记录中。 - Toni Leigh
303
重置当前分支到与远程分支origin/branch_to_overwrite相同的状态,包括代码和提交记录。命令为:git reset --hard origin/branch_to_overwrite - Andrew Atkinson
5
基本上,在初始的checkout -b之后,只需从develop分支进行一次pull操作,然后进行你的工作,完成后再将更改push回去。 - ldgorman
5
简短回答:删除并重新创建分支。
  1. 删除分支: git branch <branch> -D
  2. 重置到冲突之前的提交: git reset <commit> --hard
  3. 重新创建分支: git branch <branch>
  4. 设置跟踪服务器: git --set-upstream-to=origin/<branch> <branch>
  5. 拉取:git pull
- Nino Filiu
6
将所有的CRLF行尾符改为LF(以干净的方式开始),请执行以下操作:git config core.autocrlf false; git ls-files -z | xargs -0 rm; git checkout . - Chloe
显示剩余6条评论
53个回答

13088

⚠ 警告:

任何未提交到版本库的本地修改都将丢失,即使已经添加到暂存区。

但是任何未被 Git 追踪的本地文件不会受到影响。


首先,将所有origin/<branch>引用更新到最新版本:

git fetch --all

备份当前分支(例如:master):

git branch backup-master

跳转到 origin/master 上的最新提交并检出这些文件:

git reset --hard origin/master

解释:

git fetch 命令会从远程下载最新的代码,但不会尝试合并或变基任何内容。

git reset 命令将主分支重置为刚刚获取的内容。使用 --hard 选项会将你工作目录中的所有文件更改为与 origin/master 中的文件匹配。


维护当前的本地提交

[*]: 值得注意的是,在重置之前,可以通过从 master 创建分支来维护当前的本地提交:

git checkout master
git branch new-branch-to-save-current-commits
git fetch --all
git reset --hard origin/master

在此之后,所有旧的提交将被保存在new-branch-to-save-current-commits分支中。

未提交的更改

未提交的更改,即使已暂存(使用git add),也将丢失。确保stash或提交您需要的任何内容。例如,运行以下命令:

git stash

之后(在执行 git reset 后),再次应用这些未提交的更改:

git stash pop

可能会创建合并冲突。

35
注意!如果您有本地未推送的提交,这将从您的分支中删除它们!这种解决方案会保留未被存储库跟踪的文件,但会覆盖其他所有内容。 - Matthijs P
563
这是一个常见的问题,因此我想澄清这里的顶部评论。我刚刚按照这个答案中描述的命令执行了操作,它并没有删除所有本地文件。只有远程跟踪的文件被覆盖,每个已经存在的本地文件都没有受到影响。 - Red
46
如果你从一个远程分支名不是“master”的仓库拉取代码,使用 git reset --hard origin/分支名。意思是重新设置本地代码为远程分支的最新代码,并强制覆盖本地修改。 - Abbas Gadhia
245
鉴于本问题和答案获得的点赞数,我认为 git 应该加入一个命令,类似于“git pull -f”。 - Sophivorus
24
在执行硬重置之前未推送的提交可以通过使用 git reflog 进行恢复,该命令会列出所有提交记录,包括没有基础的记录。但在使用 git gc 清理本地副本之前,这些记录都有可能会丢失。 - Koen.
显示剩余30条评论

1366

这将移除所有未提交的更改,即使已暂存,
然后进行拉取操作:

git reset --hard HEAD
git pull

但是任何未被Git跟踪的本地文件都不会受到影响。

34
我已经完成这个任务,然后发现一些本地文件没有在版本库中,但仍保存在磁盘上。 - Piotr Owsiak
42
我认为这不正确。上述操作将执行合并,而不是问题中要求的覆盖。我没有答案,目前正在寻找中。此时,我切换到包含要保留代码的分支“git checkout BranchWithCodeToKeep”,然后执行“git branch -D BranchToOverwrite”,最后执行“git checkout -b BranchToOverwrite”。现在,您将在分支BranchToOverwrite上获得来自BranchWithCodeToKeep的完全代码,无需执行合并。 - felbus
308
尝试使用 "git fetch --all" 命令,而非 "git pull" 来合并代码,然后再使用 "git reset --hard origin/master" 命令进行更新。请注意,翻译后的内容保持原意,语言通俗易懂,并且没有其他额外的信息。 - Lloyd Moore
11
没错,@lloydmoore的解决方案对我也管用。最好把它作为答案而不仅仅是评论。 - Max Williams
6
这将重置当前更改,使其回到上次拉取的分支提交状态。然后,git pull会合并最新分支的更改。这正好实现了我想要做的事情。谢谢! - Codeversed
显示剩余11条评论

596

警告: git clean 会删除所有未跟踪的文件/目录,且无法撤销。


有时候仅使用clean -f是不够的。如果你有未跟踪的目录,还需要使用-d选项:

# WARNING: this can't be undone!

git reset --hard HEAD
git clean -f -d
git pull

警告: git clean 命令会删除所有未跟踪的文件/目录,且无法撤销。

建议先使用 -n--dry-run)标志。这将显示将要被删除的内容,但不会实际执行删除操作:

git clean -n -f -d

示例输出:

Would remove untracked-file-1.txt
Would remove untracked-file-2.txt
Would remove untracked/folder
...

2
你可以给 git clean 传递一个路径参数,以便更具体地指定要删除的内容,避免删除未被跟踪的不冲突的文件。 - joachim
8
我认为情景描述已经很清楚地表明他并不真的想要扔掉这些内容,而是想让 git 停止在覆盖文件时产生阻碍。@Lauri,这不应该发生在你身上。不幸的是,人们似乎误读了情景描述的本质 - 请参考我的建议。 - Hedgehog
26
最后,当 make clean 未能清除所有内容时,使用 git clean -f -d 就非常方便了。 - earthmeLon
9
除非它们被添加到.gitignore中,否则它们将会被包含进来。 - Bleeding Fingers
10
你可能需要使用git clean -dfx命令。其中的-x选项会忽略.gitignore文件中的内容。通常,构建产物会被列入.gitignore文件中。 - Paul Draper
显示剩余5条评论

489

我认为Hedgehog的回答很糟糕。虽然Hedgehog的回答可能更好一些,但我认为它不够优雅。我找到的方法是使用fetchmerge来定义一个策略。只要您没有试图用其覆盖的文件之一来强制覆盖,这样做应该可以保留您的本地更改。

首先提交您的更改

 git add *
 git commit -a -m "local file server commit message"

然后获取更改并在出现冲突时进行覆盖

 git fetch origin master
 git merge -s recursive -X theirs origin/master

-X 是一个选项名称,theirs 是该选项的值。如果存在冲突,您选择使用their更改(另一个选项是ours更改)。


76
到目前为止,这是我看过的最好的答案。虽然我没有尝试过,但与其他答案不同的是,这个答案并不试图彻底删除所有未跟踪的文件,这是非常危险的事情,原因显而易见。 - huyz
9
同样的方法适用于我处理一次大规模合并(GitHub 拉取请求)时,我只想在原有的基础上接受所有更改。回答得很好!在我的情况下,最后两个命令是:1)git fetch other-repo;2)git merge -s recursive -X theirs other-repo/master - quux00
5
这将覆盖与仓库文件的任何冲突,而不是您本地的文件,对吗? - Nathan F.
7
最佳答案。最高被接受的答案让我处于分离头状态。 我切换回本地主分支并运行“git merge -X theirs origin/master”命令。 - petergus
12
我只是想让Git覆盖所有内容并停止对此发表意见。毕竟,我只是在我的工作电脑和一些树莓派系统之间使用它。希望有一个强制覆盖选项,至少对于项目负责人来说。 - clockw0rk
显示剩余8条评论

424

不要做以下这样的事情:

git fetch --all
git reset --hard origin/master

我建议按照以下步骤进行:

git fetch origin master
git reset --hard origin/master

如果你要重置到origin/master分支,那么就不需要获取所有的远程仓库和分支对吧?


4
你的回答正是你所需要的,符合你的声誉需求。我必须问一下,这是否也会删除所有未被追踪的文件? - Nicolas De Jay
7
是的,我大部分声誉都来自这里 :) 这也会删除所有未被追踪的文件。这是我忘记的东西,而且就在2天前让我痛苦地想起了它... - Johanneke
2
请查看此答案的评论:https://dev59.com/i3NA5IYBdhLWcg3wAI7e#8888015 - Johanneke
未跟踪的文件不会受到git reset的影响。如果你也希望将它们一并删除,请先执行 git add .,然后再执行 git reset --hard - Johanneke
2
这正是我所需要的:覆盖远程存在的未被跟踪的文件,并保留其他所有内容。 - Ledazinha
显示剩余4条评论

160

看起来最好的方法是首先进行:

git clean

要删除所有未跟踪的文件,然后继续进行常规的 git pull 操作...


5
我尝试使用 "git clean" 解决相同的问题,但没有解决它。git 状态显示 "Your branch and 'origin/master' have diverged,

and have 2 and 9 different commit(s) each, respectively." 而 git pull 则显示类似于你上面提到的东西。

- slacy
49
git clean 是一种相对粗暴的工具,可能会丢弃你想要保留的许多东西。最好先删除或重命名 git 提示的文件,直到拉取成功为止。 - Neil Mayhew
3
我认为一般情况下这个方法行不通。有没有一种通过强制 git pull 实现基本的 git clone 远程操作的方法? - mathtick
20
@git fetch origin && git reset --hard origin/master - Arrowmaster
4
在这里,git clean是最好的答案吗?似乎删除文件并不一定是提问者想要的。他们要求的是“覆盖本地文件”,而不是删除。 - JohnAllen
显示剩余8条评论

135

警告:如果你的.gitignore文件中有directory/*条目,那么这样做将永久删除你的文件。

一些回答似乎很糟糕。 @Lauri按照David Avsajanishvili的建议所做的事情就是一个例子。

更好的方式(git > v1.7.6):

git stash --include-untracked
git pull

稍后您可以清理stash历史记录。

手动逐个删除:

$ git stash list
stash@{0}: WIP on <branch>: ...
stash@{1}: WIP on <branch>: ...

$ git stash drop stash@{0}
$ git stash drop stash@{1}

彻底地,一次性的:

$ git stash clear

当然,如果你想回到之前保存的内容:

$ git stash list
...
$ git stash apply stash@{5}

3
不,我不这么认为。Stashing只是将未提交的文件移出了路径。上述操作还会移动(stash)git没有跟踪的文件。这可以防止尚未从远程拉取到您的机器上但您已经创建的文件被拉取。而且这一切都不会破坏未提交的工作。希望这样说得清楚吗? - Hedgehog
4
如果您没有1.7.6版本,您可以通过临时将整个存储库添加到git中,然后立即隐藏它来模拟“--include-untracked”。 - nategood
4
我同意刺猬的观点。如果你按照这里流行的答案去做,很可能会发现你无意中杀死了很多你不想失去的东西。 - AfroRick
2
我有其他未被跟踪的文件——除了合并/拉取要覆盖的那个文件之外,所以这个解决方案最好。git stash apply将所有未被跟踪的文件都恢复了,但是(正确地)排除了合并已经创建的文件:“已存在,无法检出”。完美解决。 - BigBlueHat
3
这是最干净的答案,应该被采纳。为了少打一些字,您可以使用简写形式: 'git stash -u'。 - ccpizza
显示剩余3条评论

118

你可能会发现这个命令有助于抛弃本地修改:

git checkout <your-branch> -f

然后进行清理操作(从工作树中删除未跟踪的文件):

git clean -f

如果您想除了未跟踪的文件之外,还要删除未跟踪的目录:

git clean -fd

我认为场景描述已经很清楚地表明他并不想丢弃内容。相反,他想要的是停止Git在覆盖文件时出现问题。请看我的建议。 - Hedgehog
5
虽然这个答案可能不完全符合描述,但它仍然让我避免了与回车符的Git纠缠的挫败感(即使自动crlf为false)。当 git reset --hard HEAD 不会让您的修改文件状态变为 “无” 时,这些“-f”标志非常有用。非常感谢。 - Kellindil
"git clean -fd" saved me - Jzapata

105

不要使用git pull合并代码,尝试以下操作:

git fetch --all

随后执行:

git reset --hard origin/master


这在脚本中不起作用,因为你必须知道分支名称。看看我的通用解决方案。 - warch

77

对我有用的唯一方法是:

git reset --hard HEAD~5

这将带您回到五个提交之前,然后使用

git pull

我发现通过查找如何撤销Git合并


这是最终对我起作用的方法,因为我已经强制推送了我的分支到原始仓库,并且在尝试将其拉到我的远程仓库时一直遇到合并冲突。 - jwfrench
嗨,实际上这是一个“变通方法”的技巧,但非常有效。因为有些冲突可能只会在几次提交中发生,那么撤销5次提交将确保与远程代码没有冲突。 - Hoang Le

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