如何强制“ git pull”覆盖本地文件?


7176

如何强制覆盖上的本地文件git pull

该方案如下:

  • 团队成员正在修改我们正在工作的网站的模板
  • 他们正在将一些图像添加到图像目录(但是忘记在源代码控制下添加它们)
  • 他们通过邮件将图像发送给我
  • 我将图像添加到源代码管理下,并将其与其他更改一起推送到GitHub
  • 他们无法从GitHub提取更新,因为Git不想覆盖其文件。

这是我得到的错误:

错误:未跟踪的工作树文件“ public / images / icon.gif”将被合并覆盖

如何强制Git覆盖它们?这个人是设计师-通常,我会手工解决所有冲突,因此服务器具有他们只需要在计算机上更新的最新版本。


17
任何读过此文章认为可能会丢失文件的人,我一直处于这个位置,发现Sublime Text的缓冲区已救了我-如果我在处理某些内容,则通过尝试解决与此类似的问题或使用意外删除了所有内容这个问题的答案,并且已经在Sublime中打开了文件(很有可能),那么文件仍然会存在Sublime,或者就在那儿,或者在撤消历史中
Toni Leigh

61
git reset --hard origin/branch_to_overwrite
安德鲁·阿特金森

1
基本上,仅在初始签出-b之后才从develop中提取。做你的工作,然后推回去
。– ldgorman

1
简短的答案:删除并重新创建分支。1.删​​除分支:git branch <branch> -D2.在冲突之前重置为提交:git reset <commit> --hard3.重新创建分支:git branch <branch>4.将跟踪设置为服务器:git --set-upstream-to=origin/<branch> <branch> 5. Pull: git pull`
Nino Filiu

1
要将所有CRLF更改为LF结尾,(开始清理)git config core.autocrlf false; git ls-files -z | xargs -0 rm; git checkout .
Chloe

Answers:


10023

重要提示:如果您进行任何本地更改,它们将会丢失。不论有没有--hard选项,任何未推送的本地提交都将丢失。[*]

如果您有Git 不能跟踪的任何文件(例如,上载的用户内容),这些文件将不会受到影响。


我认为这是正确的方法:

git fetch --all

然后,您有两个选择:

git reset --hard origin/master

或如果您在其他分支机构:

git reset --hard origin/<branch_name>

说明:

git fetch 从远程下载最新版本,而无需尝试合并或重新设置任何内容。

然后,git reset将master分支重置为您刚获取的分支。该--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 stash

然后重新应用这些未提交的更改:

git stash pop

14
小心!如果您有本地未推送的提交,则将其从您的分支中删除!此解决方案不会使未跟踪的文件保持在存储库中不变,但会覆盖其他所有内容。
Matthijs P 2012年

479
这是一个很普遍的问题,所以我想在这里澄清一下。我只是按照此答案中的描述执行了命令,但尚未删除所有本地文件。仅覆盖了远程跟踪的文件,并且保留了此处的每个本地文件。
2012年

14
如果您要从远程分支名称与“ master”不同的回购中提取信息,请使用git reset --hard origin/branch-name
Nerrve 2013年

95
考虑到对这个问题和答案的支持,我认为git应该合并一个命令,如git pull -f
Sophivorus 2014年

7
可以使用来恢复硬重置之前未推送的提交git reflog,该提交列出了所有提交,也包括没有基础的提交。直到你清理你的本地副本使用git gc,那么一切都完了
公园。

933

尝试这个:

git reset --hard HEAD
git pull

它应该做您想要的。


16
我已经做到了,并且一些不再在回购中的本地文件留在了磁盘上。
Piotr Owsiak

26
我认为这是不正确的。上面的代码将执行合并,而不是覆盖问题中要求的合并:“如何强制git覆盖它们?” 我没有答案,我目前正在寻找..此刻,我切换到要保留“ git checkout BranchWithCodeToKeep”代码的分支,然后执行“ git branch -D BranchToOverwrite”,最后“ git checkout -b BranchToOverwrite”。您现在将在分支BranchToOverwrite上从BranchWithCodeToKeep获得确切的代码,而不必执行合并。
felbus

252
而不是使用“ git pull”合并,请尝试git fetch --all后跟“ git reset --hard origin / master”
Lloyd Moore'2

5
是的,@ lloydmoore解决方案为我工作。可以做一个答案,而不只是评论。
Max Williams

2
这会将当前更改重置回上次提交的分支提交。然后git pull合并来自最新分支的更改。正是我想要的。.谢谢!
2014年

459

警告: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
...

33
太棒了...反对我的dotfiles文件...在我的主目录中。很好,我在那里真的没有什么要紧的……
Lauri

7
我认为场景描述清楚地表明,他真的不想扔掉内容。相反,他想要的是阻止git baulking覆盖文件。@Lauri,这不应该发生在您身上。不幸的是,人们似乎误解了场景描述的本质-请参阅我的建议。
刺猬2012年

19
最后。当make clean无法清理所有内容时,git clean -f -d很方便。
EarthmeLon 2012年

7
@crizCraig,除非已添加它们.gitignore
出血手指

5
@earthmeLon,您可能想要这样做git clean -dfx。该-x忽略的.gitignore。通常,您的构建产品将位于.gitignore中。
保罗·德雷珀

384

像刺猬一样,我认为答案很糟糕。但是,尽管刺猬的答案可能更好,但我认为它并没有它的优雅。我发现做到这一点的方法是通过使用已定义策略的“提取”和“合并”。应该这样做,以便保留本地更改,只要它们不是您要强制覆盖的文件之一即可。

首先提交您的更改

 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”是该选项的值。如果发生冲突,您选择使用“他们的”更改,而不是“您的”更改。


56
这是我到目前为止看到的最好的答案。我没有尝试过,但是与其他答案不同,它不会尝试取消所有未跟踪的文件,这出于明显的原因是非常危险的。
伊兹2012年

5
同上-当我做一个非常大的合并(GitHub pull request)时,这对我有用,我只是想在我拥有的所有东西之上接受它。好答案!在我的情况下,最后两个命令是:1)get fetch other-repo; 2)git merge -s recursive -X theirs other-repo/master
quux00 2012年

2
这将覆盖与存储库文件而不是本地文件的所有冲突,对吗?
内森·F。

2
最佳答案。在我看来,最高的答案使我感到头疼。我切换回本地主分支并运行git merge -X theirs origin/master
petergus '16

2
这个(出色)答案的问题是,它添加了所有本地文件,有时可能不是您想要的。您可能只想添加省略的特定文件。但是最好的事情是,它使他能够做应该做的事情-在本地添加它们。您可能不需要-X他们的策略,因为它们是相同的映像。实际上,我建议先将其关闭,只是在检查“它们的”始终是正确的选择之后,找出是否存在异常,然后将其添加。但是后来,我很偏执。
Bob Kerns

279

而不是做:

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

我建议您执行以下操作:

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

如果您要重置为Origin / master分支,就不需要获取所有的遥控器和分支吗?


3
您的回答正是您代表所需要的。我必须问,这还会删除所有未跟踪的文件吗?
Nicolas De Jay

5
是的,我的大多数代表都来自这里:)这也将删除所有未跟踪的文件。两天前,我忘记了一些东西,让我很痛苦地回想起……
Johanneke 2014年

1
请参阅此其他答案的注释:stackoverflow.com/a/8888015/2151700
Johanneke 2014年

这并没有删除我的未跟踪文件;这实际上是我所期望的。对某些人而不对其他人可能有原因吗?
arichards's

未跟踪的文件不受git reset的影响。如果您也希望将其删除git add .,请先执行操作,然后再执行git reset --hard
Johanneke

131

看来最好的方法是先这样做:

git clean

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


4
我尝试使用“ git clean”解决相同的问题,但没有解决。git status表示“您的分支和'起源/主'已经分歧,#分别具有2和9个不同的提交。” 和git pull说的话与您上面的类似。
slacy

43
git clean是一个相当钝的工具,可能会丢弃很多您可能想要保留的东西。最好删除或重命名git抱怨的文件,直到拉取成功为止。
尼尔·梅休

2
我认为这通常不起作用。基本上没有办法通过强制git pull进行git clone远程吗?
mathtick 2010年

10
@mathick:git fetch origin && git reset --hard origin/master
Arrowmaster

3
git clean最好的答案吗?似乎删除文件不一定是OP想要的。他们要求“覆盖本地文件”而不是删除。
JohnAllen 2014年

111

警告,如果您在gitignore文件中有任何目录/ *条目,这样做将永久删除您的文件。

一些答案似乎很糟糕。在遵循David Avsajanishvili的建议后,@ Lauri发生了什么事情,真是太糟糕了。

而是(git> v1.7.6):

git stash --include-untracked
git pull

稍后,您可以清除存储历史记录。

手动一对一:

$ 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}

2
不,我不这么认为。隐藏只是将未提交的文件移开。上面的代码还移动(隐藏)了git无法跟踪的文件。这样可以防止已添加到远程的,尚未下拉到您的计算机上但已创建(!)的文件被下拉。所有这些都不会破坏未完成的工作。希望这有意义吗?
刺猬

3
如果您没有1.7.6,则可以--include-untracked通过临时- git add整个存储库,然后立即将其存储来简单地模拟。
nategood 2012年

3
我同意刺猬。如果您在此处进行流行解答,则很有可能会发现自己无意中杀死了许多您本不想失去的东西。
瓜迪乌斯

1
我还有其他未跟踪的文件-除了合并/拉取要覆盖的文件之外,因此此解决方案效果最佳。git stash apply带回了我所有未跟踪的文件,除了(正确地)合并已经创建的文件:“已经存在,没有签出。” 工作完美。
BigBlueHat 2013年

2
这是最干净的答案,应该被接受。要保存一些输入内容,您可以使用以下简短格式:git stash -u
ccpizza

93

您可能会发现此命令有助于丢弃本地更改:

git checkout <your-branch> -f

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

git clean -f

如果要除去未跟踪文件之外的其他未跟踪目录,请执行以下操作:

git clean -fd

我认为场景描述清楚地表明,他真的不想扔掉内容。他想要的是停止git baulking来覆盖文件。看我的建议。
刺猬2012年

3
尽管该答案可能不完全符合描述,但仍使我免于git混乱与回车符(autocrlf为false的事件)的麻烦。当git reset --hard HEAD不会给您留下“没有”修改的文件时,这些“ -f”标志会很有帮助。谢谢你
Kellindil

88

与其合并git pull,请尝试以下操作:

git fetch --all

其次是:

git reset --hard origin/master


61

唯一对我有用的是:

git reset --hard HEAD~5

这将带您退回五次提交,然后

git pull

通过查找如何撤消Git合并,我发现了这一点。


这是什么最终为我工作,因为我有力量把我支到原点回购和不断获得合并冲突试图将其拉至我的远程回购的时候..
jwfrench

嗨,实际上这是一个技巧,work around但是很有效。因为仅在少数几次提交中可能会发生一些冲突,所以还原5次提交将确保与远程代码没有冲突。
Hoang Le

54

所有这些解决方案的问题在于它们要么太复杂,要么甚至更大的问题在于它们从Web服务器中删除了所有未跟踪的文件,我们不希望这样做,因为始终存在需要的配置文件。服务器,而不是在Git存储库中。

这是我们正在使用的最干净的解决方案:

# Fetch the newest code
git fetch

# Delete all files which are being added, so there
# are no conflicts with untracked files
for file in `git diff HEAD..origin/master --name-status | awk '/^A/ {print $2}'`
do
    rm -f -- "$file"
done

# Checkout all files which were locally modified
for file in `git diff --name-status | awk '/^[CDMRTUX]/ {print $2}'`
do
    git checkout -- "$file"
done

# Finally pull all the changes
# (you could merge as well e.g. 'merge origin/master')
git pull
  • 第一条命令获取最新数据。

  • 第二个命令检查是否有任何文件要添加到存储库中,并从本地存储库中删除那些会引起冲突的未跟踪文件。

  • 第三个命令检出所有在本地修改的文件。

  • 最终,我们拉动更新到最新版本,但是这次没有任何冲突,因为回购中不再存在未跟踪的文件,并且所有本地修改的文件已经与存储库中的相同。


使用“ git merge origin / master”作为最后一行(如您在注释中所说)而不是“ git pull”会更快,因为您已经从git repo中提取了所有更改。
乔什(Josh),

1
是的,当然git merge origin/master会更快,甚至更安全。由于如果有人在删除此脚本的文件的过程中推送了新更改(这不太可能发生,但可能),则整个提取操作可​​能会失败。我输入的唯一原因pull是因为有人可能不在master分支上工作,但是在其他分支上工作,我希望脚本具有通用性。
Strahinja Kustudic 2013年

如果您有本地创建的文件(如选项文件),请将其放入.gitignore
Sebi

52

首先,尝试标准方法:

git reset HEAD --hard # To remove all not committed changes!
git clean -fd         # To remove all untracked (non-git) files and folders!

警告:仅当您未提交上述命令时,它们才会导致数据/文件丢失!如果不确定,请首先备份整个存储库文件夹。

然后再拉。

如果上述方法无济于事,并且您不关心未跟踪的文件/目录(为防万一,请首先进行备份),请尝试以下简单步骤:

cd your_git_repo  # where 'your_git_repo' is your git repository folder
rm -rfv *         # WARNING: only run inside your git repository!
git pull          # pull the sources again

这将删除所有git文件(.git/具有所有提交的dir,除外)并再次将其拉出。


为什么git reset HEAD --hard在某些情况下会失败?

  1. 中的自定义规则 .gitattributes file

    eol=lf在.gitattributes中规则可能会导致git通过将某些文本文件中的CRLF行尾转换为LF来修改某些文件更改。

    如果是这种情况,您必须提交这些CRLF / LF更改(通过在中进行查看git status),或尝试:git config core.autcrlf false暂时忽略它们。

  2. 文件系统不兼容

    当您使用不支持权限属性的文件系统时。在示例中,您有两个存储库,一个在Linux / Mac(ext3/ hfs+)上,另一个在基于FAT32 / NTFS的文件系统上。

    您会注意到,有两种不同类型的文件系统,因此,一种不支持Unix权限的文件系统基本上无法在不支持这种权限的系统上重置文件权限,因此无论--hard您如何尝试,git总是发现一些“变化”。


47

我有同样的问题。没有人给我这种解决方案,但是对我有用。

我通过以下方法解决了它:

  1. 删除所有文件。仅保留.git目录。
  2. git reset --hard HEAD
  3. git pull
  4. git push

现在可以了。


1
同样在这里。有时,只有非常艰苦的解决方案才能奏效,经常发生的情况是,仅重置和清理还不够用……
jdehaan 2011年

41

奖金:

在前面的答案中提到拉取/提取/合并时,我想分享一个有趣且富有成效的技巧,

git pull --rebase

上面的命令是我的Git生命中最有用的命令,它节省了大量时间。

在将您的新提交推送到服务器之前,请尝试使用此命令,它将自动同步最新的服务器更改(通过访存+合并),并将您的提交放在Git日志的顶部。无需担心手动拉/合并。

“ git pull --rebase”做什么中找到详细信息


3
简而言之:git pull -r
kenorb

29

我有一个类似的问题。我必须这样做:

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

6
git clean谨慎使用
nategood 2012年

29

我总结了其他答案。您可以正确执行git pull

git fetch --all
git reset --hard origin/master
git reset --hard HEAD
git clean -f -d
git pull

警告:此脚本非常强大,因此您可能会丢失所做的更改。


2
这将覆盖已修改的文件(之前已签入的文件),并将删除未跟踪的文件(从未签入的文件)。正是我想要的东西,谢谢!
styfle

3
我怀疑第三行git reset --hard HEAD可能是多余的;我的本地手册页(2.6.3)reset在第二行中说,git reset --hard origin/master “默认为所有形式的HEAD”。
理查兹(Arichards)2016年

2
@arichards我认为您的嫌疑犯是正确的,但是如果第二行(由于任何原因)不起作用,那么第三行可以很好地重置。此解决方案无需优化。我只是总结了其他答案。就这样。感谢您的评论。:)
Robert Moon

28

根据我自己的类似经验,上述Strahinja Kustudic提供的解决方案是迄今为止最好的。正如其他人指出的那样,仅执行硬重置将删除所有未跟踪的文件,这些文件可能包含许多您不想删除的内容,例如配置文件。更为安全的是,仅删除将要添加的文件,因此,您可能还希望检出将要更新的所有本地修改的文件。

考虑到这一点,我更新了Kustudic的脚本来做到这一点。我还修正了一个拼写错误(原文中缺少“”)。

#/bin/sh

# Fetch the newest code
git fetch

# Delete all files which are being added,
# so there are no conflicts with untracked files
for file in `git diff HEAD..origin/master --name-status | awk '/^A/ {print $2}'`
do
    echo "Deleting untracked file $file..."
    rm -vf "$file"
done

# Checkout all files which have been locally modified
for file in `git diff HEAD..origin/master --name-status | awk '/^M/ {print $2}'`
do
    echo "Checking out modified file $file..."
    git checkout $file
done

# Finally merge all the changes (you could use merge here as well)
git pull

使用“ git merge origin / master”作为最后一行(如您在注释中所说)而不是“ git pull”会更快,因为您已经从git repo中提取了所有更改。
乔什(Josh)

需要检出已修改的文件,因此可以100%地工作。很久以前,我使用该脚本更新了脚本,但也忘记了在此处进行更新。我也使用它与您有所不同。我签出的文件可以进行任何类型的修改,而不仅仅是M,所以它可以一直工作。
Strahinja Kustudic 2013年

24

我相信有两种可能的冲突原因,必须分别解决,据我所知,上述答案均未涉及这两种问题:

  • 未跟踪的本地文件需要手动删除(更安全)或按照其他答案中的建议删除,方法是: git clean -f -d

  • 不在远程分支上的本地提交也需要删除。IMO实现此目的最简单的方法是:(git reset --hard origin/master用您正在处理的任何分支替换“ master”,然后git fetch origin首先运行)


22

一种更简单的方法是:

git checkout --theirs /path/to/file.extension
git pull origin master

这将用git上的文件覆盖您的本地文件


21

似乎大多数答案都集中在master分支上。但是,有时候我在两个不同的地方处理同一个功能分支,并且我希望其中一个的基础能够在另一个中得到反映,而不会造成很大的麻烦。

基于RNA的答案torek的类似问题的答案的结合,我提出了一个出色的解决方案:

git fetch
git reset --hard @{u}

从分支运行此命令,它将仅将您的本地分支重置为上游版本。

也可以将其很好地放入git别名(git forcepull):

git config alias.forcepull "!git fetch ; git reset --hard @{u}"

或者,在您的.gitconfig文件中:

[alias]
  forcepull = "!git fetch ; git reset --hard @{u}"

请享用!


这个答案也很好,因为无论您在哪个分支上都可以使用它!
叶餐

19

我遇到了同样的问题,由于某种原因,即使a git clean -f -d也不会这样做。原因如下:由于某种原因,如果Git忽略了您的文件(我想通过.gitignore条目),它仍然会为以后的pull重写而烦恼,但是除非您添加,否则干净不会删除它-x


19

我知道一种更简单,更轻松的方法:

$ git branch -m [branch_to_force_pull] tmp
$ git fetch
$ git checkout [branch_to_force_pull]
$ git branch -D tmp

而已!


18

我自己通过以下方法解决了这个问题:

git checkout -b tmp # "tmp" or pick a better name for your local changes branch
git add -A
git commit -m 'tmp'
git pull
git checkout master # Or whatever branch you were on originally
git pull
git diff tmp

最后一个命令列出了本地更改内容。继续修改“ tmp”分支,直到可接受为止,然后使用以下命令合并回master:

git checkout master && git merge tmp

对于下一次,您可以通过查找“ git stash branch”来以一种更简洁的方式来处理此问题,尽管在最初的几次尝试中,stash可能会给您带来麻烦,因此,请首先在非关键项目上进行实验...


17

我有一个奇怪的情况,既不起作用git cleangit reset不起作用。我必须git index通过在每个未跟踪的文件上使用以下脚本来删除有冲突的文件:

git rm [file]

然后我可以拉得很好。


16

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


14

尽管有最初的问题,但是对于有类似问题但又不想丢失其本地文件的用户,最重要的答案可能会引起问题。例如,请参阅Al-Punk和crizCraig的评论。

以下版本将您的本地更改提交到临时分支(tmp),签出原始分支(我​​假设是master)并合并更新。您可以使用进行此操作stash,但是我发现通常简单地使用分支/合并方法会更容易。

git checkout -b tmp
git add *; git commit -am "my temporary files"
git checkout master

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

我们假设另一个存储库origin master


13

这四个命令对我有用。

git reset --hard HEAD
git checkout origin/master
git branch -D master
git checkout -b master

执行这些命令后进行检查/拉动

git pull origin master

我做了很多尝试,但最终在这些命令上获得了成功。


2
“ git branch -D master”删除该分支。所以要小心 我更喜欢使用“ git checkout origin / master -b <新分支名称>”来创建一个具有新名称的新分支,您确实需要3,4行。还建议也使用“ git clean -f”。
Chand Priyankara 2014年

13

做就是了

git fetch origin branchname
git checkout -f origin/branchname // This will overwrite ONLY new included files
git checkout branchname
git merge origin/branchname

因此,您可以避免所有不必要的副作用,例如删除要保留的文件或目录等。


12

将索引和标头重置为origin/master,但不要重置工作树:

git reset origin/master

我个人认为这是最有用的。然后,它将保留您的工作树,以便您可以再次检入它。对于我的问题,我删除了与添加的文件相同的文件,因此卡住了。很奇怪,我知道。
詹森·塞布林2014年

12

要求:

  1. 跟踪本地更改,因此这里没有人会丢失它们。
  2. 使本地存储库与远程原始存储库匹配。

解:

  1. 隐藏本地更改。
  2. 一个干净文件目录忽略的.gitignore硬复位原点

    git stash --include-untracked
    git fetch --all
    git clean -fdx
    git reset --hard origin/master
    
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.