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

如何强制覆盖git pull上的本地文件?我的本地存储库包含与服务器上的文件名相同的文件。

错误:未跟踪的工作树文件“example.txt”将被合并覆盖

7222437 次浏览

看起来最好的方法是先做:

git clean

删除所有未跟踪的文件,然后继续使用通常的git pull

这将删除所有未提交的更改,然后拉取:

git reset --hard HEADgit pull

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

git checkout <your-branch> -f

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

git clean -f

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

git clean -fd

您可以使用项目基文件夹中的文件忽略该文件:

. gitignore

public/images/*

然后拉取更改,然后从gitignore文件中删除该行。

我自己解决了这个问题:

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

其中最后一个命令给出了您的本地更改列表。继续修改“tmp”分支,直到它可以接受,然后使用以下命令合并回master:

git checkout master && git merge tmp

下一次,你可能可以通过查找“git stash分支”以更干净的方式处理这个问题,尽管stash可能会在最初的几次尝试中给你带来麻烦,所以首先在非关键项目上进行实验…

我也遇到了同样的问题。没有人给我这个解决方案,但它对我有效。

我解决了它:

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

现在起作用了。

我也遇到过类似的问题。我不得不这样做:

git reset --hard HEADgit clean -fgit pull

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


有时只是clean -f没有帮助。如果您有未跟踪的目录,还需要-d选项:

# WARNING: this can't be undone!
git reset --hard HEADgit clean -f -dgit pull

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

考虑首先使用-n--dry-run)标志。这将向您显示将删除的内容,而无需实际删除任何内容:

git clean -n -f -d

输出示例:

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

唯一对我有用的是:

git reset --hard HEAD~5

这将带你回到五次提交,然后

git pull

我通过查找如何撤消Git合并找到了它。

我也有同样的问题,出于某种原因,即使是git clean -f -d也不会这样做。原因如下:出于某种原因,如果您的文件被Git忽略(我假设是通过. gitignore条目),它仍然会担心用稍后的覆盖它,但干净不会删除它,除非您添加-x

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

git rm [file]

然后我可以拉得很好。

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

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

  • 不在远程分支上的本地提交也需要删除。IMO实现这一目标的最简单方法是:git reset --hard origin/master(将'master'替换为您正在处理的任何分支,并首先运行git fetch origin

⚠警告:

对跟踪文件的任何未提交的本地更改都将丢失。

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 mastergit branch new-branch-to-save-current-commitsgit fetch --allgit reset --hard origin/master

之后,所有旧的提交都将保留在new-branch-to-save-current-commits中。

未提交的更改

但是,未提交的更改(即使是暂存的)将丢失。确保隐藏和提交您需要的任何内容。为此,您可以运行以下操作:

git stash

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

git stash pop

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

有些答案似乎很糟糕。从劳里听从大卫·阿夫萨贾尼什维利的建议发生的事情的意义上说,很糟糕。

而是(git>v1.7.6):

git stash --include-untrackedgit pull

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

手动,一个接一个:

$ git stash liststash@{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}

像Hedgehog一样,我认为答案很糟糕。但是,尽管Hedgehog的答案可能更好,但我认为它并没有那么优雅。我发现做到这一点的方法是使用fetchmerge并定义策略。这应该使您的本地更改得到保留,只要它们不是您试图强制覆盖的文件之一。

首先提交您的更改

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

然后获取更改并覆盖如果有冲突

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

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

首先,尝试标准方法:

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 folderrm -rfv *         # WARNING: only run inside your git repository!git pull          # pull the sources again

这将删除所有git文件(排除.git/ dir,您有所有提交)并再次拉取它。


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

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

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

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

  2. 文件系统不兼容

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

    正如你所注意到的,有两种不同类型的文件系统,所以不支持Unix权限的系统基本上不能重置不支持这种权限的系统上的文件权限,所以无论你怎么尝试--hard,git总是检测到一些“变化”。

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

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

# Fetch the newest codegit fetch
# Delete all files which are being added, so there# are no conflicts with untracked filesfor file in `git diff HEAD..origin/master --name-status | awk '/^A/ {print $2}'`dorm -f -- "$file"done
# Checkout all files which were locally modifiedfor file in `git diff --name-status | awk '/^[CDMRTUX]/ {print $2}'`dogit checkout -- "$file"done
# Finally pull all the changes# (you could merge as well e.g. 'merge origin/master')git pull
  • 第一个命令获取最新数据。

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

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

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

不要与git pull合并,试试这个:

git fetch --all

其次是:

git reset --hard origin/master

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

git reset origin/master

根据我自己类似的经验,Strahinja Kustudic提供的解决方案是目前为止最好的。正如其他人指出的,简单地进行硬重置将删除所有未跟踪的文件,其中可能包含许多您不想删除的内容,例如配置文件。更安全的是仅删除即将添加的文件,就此而言,您可能还希望签出任何即将更新的本地修改的文件。

考虑到这一点,我更新了Kustudic的脚本来做到这一点。我还修复了一个错字(原始中缺少的一个)。

#/bin/sh
# Fetch the newest codegit fetch
# Delete all files which are being added,# so there are no conflicts with untracked filesfor file in `git diff HEAD..origin/master --name-status | awk '/^A/ {print $2}'`doecho "Deleting untracked file $file..."rm -vf "$file"done
# Checkout all files which have been locally modifiedfor file in `git diff HEAD..origin/master --name-status | awk '/^M/ {print $2}'`doecho "Checking out modified file $file..."git checkout $filedone
# Finally merge all the changes (you could use merge here as well)git pull

而不是做:

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

我建议做以下事情:

git fetch origin mastergit reset --hard origin/master

如果您要重置到原始/主分支,则无需获取所有远程和分支,对吗?

似乎这里的大多数答案都集中在master分支上;然而,有时我在两个不同的地方处理同一个功能分支,我希望在一个分支中的重新定位反映在另一个分支中,而不需要太多的跳跃。

基于RNA的答案托雷克对类似问题的回答的组合,我想出了一个非常有效的方法:

git fetchgit 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}"

好好享受!

这四个命令为我工作。

git reset --hard HEADgit checkout origin/mastergit branch -D mastergit checkout -b master

执行这些命令后检查/拉取

git pull origin master

我尝试了很多,但最终用这些命令取得了成功。

尽管最初的问题,顶部的答案可能会给有类似问题但不想丢失本地文件的人带来问题。例如,请参阅Al-Punk和crizCraig的评论。

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

git checkout -b tmpgit add *; git commit -am "my temporary files"git checkout master
git fetch origin mastergit merge -s recursive -X theirs origin master

我们假设其他存储库origin master

更简单的方法是:

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

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

我总结了其他答案。你可以执行git pull而不会出错:

git fetch --allgit reset --hard origin/mastergit reset --hard HEADgit clean -f -dgit pull

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

职位要求:

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

解决方案:

  1. Stash本地更改。
  2. 拿过来文件目录中的干净忽略. gitignore硬复位起源

    git stash --include-untrackedgit fetch --allgit clean -fdxgit reset --hard origin/master

我知道一个更容易和更少痛苦的方法:

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

就是它了!

我使用此命令删除阻止我进行拉/合并的本地文件。但要小心!首先运行git merge …以查看是否只有您真正想要删除的文件。

git merge origin/master 2>&1 >/dev/null | grep ^[[:space:]] | sed s/^[[:space:]]//g | xargs -L1 rm
  • git merge列出了所有这些文件。它们前面有一些空格。
  • 2>&1 >/dev/null将错误输出重定向到标准输出,以便由grep拾取。
  • grep ^[[:space:]]仅过滤具有文件名的行。
  • sed s/^[[:space:]]//g从一开始就修剪空白。
  • xargs -L1 rm对每个文件调用rm,删除它们。

小心处理:无论git merge输出什么,rm将被调用行以空格开头。

照做就是了

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

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

奖金:

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

git pull --rebase

上面的命令是我Git生活中最有用的命令,节省了很多时间。

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

什么是"git拉-rebase"做什么?中查找详细信息。

我通读了所有答案,但我正在寻找一个命令来执行此操作。这是我所做的。向. gitconfig添加了一个git别名

[alias]fp = "!f(){ git fetch ${1} ${2} && git reset --hard ${1}/${2};};f"

运行您的命令

git fp origin master

相当于

git fetch origin mastergit reset --hard origin/master

我试图在Angular2-Webpack Starter上使用Material2分支,并且花了很多时间。这是我可以下载和使用该分支的唯一方法。

git clone --depth 1 https://github.com/angularclass/angular2-webpack-starter.git
cd angular2-webpack-starter/
git checkout -b material2

打开项目文件夹并删除所有非隐藏文件和文件夹。保留所有隐藏的。

git add .
git commit -m "pokemon go"
git reset --hard
git pull origin material2

(当编辑器弹出时,点击': wq',然后按输入

现在你准备好了。

这是恢复更改的最佳实践:

  • git commit提交您的分阶段更改,以便将它们保存在重试中(见下文)
  • git fetch获取最新的上游更改
  • git reset --hard origin/master硬重置到原始主分支

重排本地存储库中正在更新的记录分支和其他引用。或者简单地说-重排您的更改历史

因此,提交总是一个很好的做法。提交被附加到reflg中,这确保您始终有办法检索已删除的代码。

不要使用git reset --hard。这将擦除他们的更改,这很可能是完全不受欢迎的。相反:

git pullgit reset origin/mastergit checkout <file1> <file2> ...

当然,您可以使用git fetch而不是git pull,因为它显然不会合并,但如果您通常拉取,则继续在此处拉取是有意义的。

所以这里发生的是git pull更新您的源/主参考git reset更新您的本地分支引用在不更新任何文件的情况下与源/主相同,所以你的签出状态不变;然后根据需要git checkout将文件恢复到本地分支索引状态。如果在live和上游master上添加了完全相同的文件,索引在重置后已经与文件匹配,所以在常见情况下你根本不需要做git checkout

如果上游分支还包含要自动应用的提交,您可以遵循流程的细微变化:

git pullgit merge <commit before problem commit>git reset <problem commit>git checkout <file1> <file2> ...git pull

在Windows上,执行以下命令:

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

这是一个通用解决方案如果你不总是想粘贴分支名称或者你想在脚本中自动执行此操作

git fetchgit reset --keep origin/$(git rev-parse --abbrev-ref HEAD)

如果您也想重置本地更改:

git fetchgit reset --hard origin/$(git rev-parse --abbrev-ref HEAD)

您还可以使用此命令添加bash别名:

alias gplf='git fetch && echo "HEAD was at $(git rev-parse --short HEAD)" && git reset --hard origin/$(git rev-parse --abbrev-ref HEAD)'

1:重置到上一个提交

git reset --hard HEAD

2:删除未跟踪的文件

git clean -f

3:拉取提交

git pull

来源:

您可以尝试git pull --force,或者通过使用git stash然后运行git pull来隐藏您的提交。

执行git拉取后,您将获得不匹配的文件列表。如果文件数量不是很大,那么您可以签出这些文件,此操作将覆盖这些文件。

git检出--<文件名>

如果为了快速检查我修改了服务器上的本地文件,我通常会这样做(没有推荐并且可能是您遇到此问题的原因:D),我在找到解决方案后检查更改的文件。

尽管这个问题已经有很多答案,但最初的问题是为了解决这个问题

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

由于二进制文件不能合并,一个简单的答案是

git checkout public/images/icon.gif

这样,文件将恢复它在此分支中的先前状态。

如果我不想丢失我的更改,我通常会做git stash,如果我不关心本地修改的文件,我会做类似git checkout .的事情。IMO比reset --hardclean简单得多……所有这些东西更适合离开分支,就像在远程一样,包括提交、未跟踪的文件,而不仅仅是解决本地修改的文件。

我已经尝试了我能在这里找到的大部分东西,没有一个在我的情况下奏效。

什么工作是#0

步骤1.(可选)
从本地存储库的根目录,保存备份并清空当前文件夹

mkdir -p ../<branch>-bkp && mv --backup=t * ../<branch>-bkp

步骤2。从远程存储库下载分支的所有文件和文件夹:

git checkout <branch> && git add -A . && git reset --hard origin/<branch> && git pull

您应该将<branch>替换为分支的名称你想要覆盖。

评论:

  • 您可能更喜欢手动备份并删除当前文件和文件夹而不是步骤1.
    事实上,我推荐在GUI中使用文件处理程序执行此操作您的操作系统。
  • 如果跳过步骤1,请注意:您将失去本地的所有工作仓库!
  • 重要:如果你在步骤2中省略了git pull
    您可能无法从远程存储库获取最新版本
    根据下面的第二个引用,git reset --hard
    重置暂存区和工作目录以匹配最最近提交
    我的经验反驳了这一说法!
  • 如果你运行git reset --hard origin/<branch_to_overwrite>不首先从本地存储库中删除所有文件和文件夹,请注意,任何仍在放置的垃圾文件都可能潜入远程git push,即使这不是你的意图。
    步骤2中的额外git add -A .可以防止这种情况发生选择省略步骤1

参考资料:
https://gitforwindows.org/
https://www.atlassian.com/git/tutorials/undoing-changes/git-reset
https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog

解决这个问题的另一种方法是首先使用git stash隐藏任何未提交的更改,然后运行

git pull --rebase=interactive -s recursive -X theirs

在交互式rebase中,您可以将所有本地不需要的提交更改为drop,这将摆脱它们并将您留在远程分支的头部,而无需引入合并提交。

现在你可以运行git stash apply如果你有本地藏匿的改变,你想带回来。

如果您正在处理代码并发现新更改是一个巨大的错误或不需要的,您可以简单地使用替代方案,例如:

git restore .

其中。表示目录中存在的所有文件。

“我的本地更改很小,或者我的更改不起作用。我只想将所有内容重置为原始。我知道我所有的本地更改都会丢失。”

如果是这样的话:

git reset --hardgit pull

我不知道为什么没有人谈论FETCH_HEAD

git fetch origin master && git reset --hard FETCH_HEAD

如果你想把它放在别名中,命令将是:

git config --global alias.fpull '!git fetch origin master && git reset --hard FETCH_HEAD'

对于那些不喜欢reset的人,我喜欢这种方法:

git checkout branchname      # go to your branchgit fetch origin branchname  # fetch the remotegit checkout -b backup       # optionally, mark your remote as a backupgit branch -f branchname origin/branchname # force your local branch to be equal to the fetched origin/branchname

如果你想要幂等,你可以使用“git rm-rf--cache”。

cd $GIT_ROOT_DIRECTORYgit fetchgit rm -rf --cached .git reset --hard HEADgit clean -dfgit pull origin $TARGET_BRANCH