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

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

方案如下:

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

这是我得到的错误:

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

回答

重要提示:如果您有任何本地更改,它们将丢失.有或没有--hard选项,任何未被推送的本地提交都将丢失.[*]

如果您有任何未被 Git跟踪的文件(例如上传的用户内容),则这些文件不会受到影响.


我认为这是正确的方法:

git fetch --all

然后,您有两个选择:

git reset --hard origin/master

或者如果你在其他分支上:

git reset --hard origin/<branch_name>

说明:

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 stash

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

git stash pop
  • 这是一个很受欢迎的问题,所以我想在这里澄清一下最热门的评论.我只是执行了本答案中描述的命令,但它没有删除所有本地文件.只覆盖了远程跟踪的文件,并且此处的所有本地文件都保持不变.
  • 考虑到这个问题和答案的赞成量,我认为git应该包含像``git pull -f`这样的命令.
  • 这对我有用,我的本地文件没有被删除.
  • 如果您从远程分支名称与"master"不同的仓库中提取,请使用`git reset --hard origin/branch-name`
  • 小心!如果您有本地未提交的提交,这将从您的分支中删除它们!此解决方案保留未在存储库中的未跟踪文件,但覆盖其他所有内容.
  • 使用`git reflog`可以恢复在硬复位之前没有推送的提示,它列出了所有提交,也列出了没有基础的提交.在使用`git gc`清理本地副本之前,所有内容都将丢失
  • 为了正确,未提交的更改将丢失,但旧提交正在悬空,等待垃圾回收.你仍然可以在`git reflog`中看到它们并用`git reset --hard HEAD @ {1}`移动你的`HEAD`.
  • 鲜为人知的事实 - 你可以用老式的`tar -czf myrepodir.tar.gz myrepodir/.`备份你的整个git repo.如果你的repo由于git古怪而搞得一团糟,删除它并从`tar.gz`文件恢复到*ACTUALLY*回到你尝试这个命运多变的实验之前的位置.只需确保在`myrepodir /`或``.git`后面有`.`,其他隐藏文件将无法保存!
  • @FelipeSchenone实际上有`git pull -f`,但它没有做我们都希望它做的事情.
  • 想在此指出,它还将删除在未远程跟踪的任何其他分支中所做的任何更改.我失去了我,希望别人小心.
  • 使用本地文件备份文件夹,包括.git文件夹.现在你不能"松散"任何东西,如果这个修复不适合你; 你可以制作另一个副本并尝试别的东西.不要在单个文件夹中操作并信任git,就好像它是100%可靠的备份工具一样.一个错字,特别是在分支土地上,可能是一场噩梦.我建议一个备份旧学校到tar.gz文件夹,然后从最新的副本运行git.
  • @Red是的,如果你想删除未跟踪的所有内容,甚至被忽略,请在重置后重新使用git clean -dxf.
  • 如果你只想要一个分支,那么`fetch origin master`可能更合适...
  • @mcv要保留你的本地提交,你需要`git reset --hard HEAD`,然后你可以通过`git merge origin/master`来关注.

试试这个:

git reset --hard HEAD
git pull

它应该做你想要的.

  • 而不是使用'git pull'合并,尝试git fetch --all后跟'git reset --hard origin/master'
  • 我不认为这是正确的.以上将执行合并,而不是覆盖问题中请求的:"如何强制git覆盖它们?" 我没有答案,我目前正在寻找它..此刻我切换到我希望保留"git checkout BranchWithCodeToKeep"代码的分支,然后做"git branch -D BranchToOverwrite"然后最后"git checkout -b BranchToOverwrite".现在,您将在BranchToOverwrite分支上获得BranchWithCodeToKeep的确切代码,而无需执行合并.
  • 我已经这样做了,一些不再存在的本地文件留在了磁盘上.
  • 是的,@ lloydmoore解决方案为我工作.可以做一个答案,而不仅仅是一个评论.
  • 这会将当前更改重置回拉到的最后一个分支提交.然后git pull合并来自最新分支的更改.这完全是我想要它做的..谢谢!
  • 很好的答案,但请添加更多细节,我的意思是有些人可能对重置一无所知并丢失了他们的文件......

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


有时候只是clean -f没有帮助.如果您有未跟踪的DIRECTORIES,还需要-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
...
  • 太棒了......把它放在我的dotfiles repo上......在我的主目录中.很好,我没有真正有重要的东西......
  • **最后**.当make clean无法清理所有东西时,git clean -f -d很方便.
  • @crizCraig除非将它们添加到`.gitignore`中
  • 我认为场景描述清楚地表明他并不想丢弃内容.而他想要的是阻止git笨重地覆盖文件.@Lauri,这不应该发生在你身上.不幸的是,人们似乎误读了场景描述的本质 - 请参阅我的建议.
  • @earthmeLon,因为你可能想要`git clean -dfx`.`-x`忽略.gitignore.通常,您的构建产品将位于.gitignore中.

像Hedgehog一样,我认为答案很糟糕.但是虽然刺猬的答案可能会更好,但我认为它并不像它那样优雅.我发现这样做的方法是使用"fetch"和"merge"与定义的策略.这应该使它保持本地更改,只要它们不是您试图强制覆盖的文件之一.

首先提交您的更改

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

然后获取更改并在发生冲突时覆盖

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

"-X"是选项名称,"他们的"是该选项的值.如果存在冲突,您选择使用"他们的"更改,而不是"您的"更改.

  • 这是我到目前为止看到的最佳答案.我没有尝试过,但与其他答案不同的是,这并不会试图破坏所有未跟踪的文件,这显然是非常危险的.
  • 我只是想让该死的 git 覆盖所有内容并闭嘴。毕竟我只是在我的工作电脑和一些树莓派系统之间使用它。希望强制覆盖选项,至少对于项目负责人
  • 同上 - 当我做一个非常大的合并(GitHub拉动请求)时,这对我有用,我只想在我拥有的东西之上接受它.好答案!在我的例子中,最后两个命令是:1)`get fetch other-repo`; 2)`git merge -s recursive -X theirs-repo/master`
  • 最佳答案。在我的情况下,最高接受的答案让我头昏眼花。我切换回本地主分支并运行`git merge -X theirs origin/master`
  • 这将覆盖与存储库文件而不是本地文件的任何冲突,对吗?
  • 这个(优秀)答案的问题是它添加了所有本地文件,有时可能不是您想要的。您可能只想添加被省略的特定文件。但最好的事情是,它让他做他应该做的事情——在本地添加它们。您可能不需要 -X 他们的策略,因为它们是相同的图像。事实上,我建议一开始就放弃它,只是为了找出是否有任何异常,如果有,在检查“他们的”总是正确的选择后添加它。但后来,我很偏执。

而不是做:

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

我建议做以下事情:

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

如果要重置为原点/主分支,是否需要获取所有遥控器和分支?

  • 是的,我的大多数代表来自这里:)这也将删除所有未跟踪的文件.我忘记的东西,并在2天前痛苦地提醒...
  • 您的回答正是您的代表所需要的.我必须问,这是否也会删除所有未跟踪的文件?

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

git clean

要删除所有未跟踪的文件,然后继续正常git pull...

  • git clean是一种相当钝的工具,可能会丢掉很多你想要保留的东西.最好删除或重命名git抱怨的文件,直到拉取成功为止.
  • @mathick:`git fetch origin && git reset --hard origin/master`
  • 我尝试使用"git clean"来解决同样的问题,但它没有解决它.git status说"你的分支和'origin/master'分歧了,#并分别有2个和9个不同的提交." 和git pull说了类似于你上面的东西.
  • "git clean"是最好的答案吗?似乎删除文件不一定是OP想要的.他们要求"覆盖本地文件"而不是删除.
  • 我认为这不起作用.难道没有办法通过强制git pull基本上做一个git clone remote吗?

警告,如果您的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}
  • 如果你没有1.7.6,你可以简单地通过暂时`git add`整个仓库模仿`--include-untracked`,然后立即存储它.
  • 不,我不这么认为。存储只是将未提交的文件移开。以上还移动(隐藏)git 不跟踪的文件。这可以防止已添加到远程的文件尚未下拉到您的计算机 - 但您已创建 (!) - 被下拉。所有这些都不会破坏未提交的工作。希望这是有道理的?
  • 我同意Hedgehog.如果你在这里做了流行的答案,你很可能会发现你无意中杀死了很多你并不想丢失的东西.
  • 这是最干净的答案,应该是公认的答案.为了节省一些打字,您可以使用简短形式:`git stash -u`.

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

git checkout <your-branch> -f

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

git clean -f

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

git clean -fd
  • 虽然这个答案可能不完全符合描述,但它仍然让我免受git错综复杂的回车(带有autocrlf false的事件).当git reset --hard HEAD没有给你留下"no"修改过的文件时,这些"-f"标志非常有用.谢谢一堆.

git pull试试这个: 而不是合并

git fetch --all

其次是:

git reset --hard origin/master.


唯一对我有用的是:

git reset --hard HEAD~5

这将带你回五次提交然后再回来

git pull

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


所有这些解决方案的问题是,他们都是要么过于复杂,或者一个更大的问题,是他们从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 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. 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总是检测到一些"变化".


我有同样的问题.没有人给我这个解决方案,但它对我有用.

我通过以下方式解决了

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

现在它有效.


奖金:

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

git pull --rebase

以上命令是我Git生活中最有用的命令,可以节省大量时间.

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

"git pull --rebase"中查找详细信息.

  • In short: `git pull -r`.

我遇到了类似的问题.我不得不这样做:

git reset --hard HEAD
git clean -f
git pull
  • 谨慎使用`git clean`

我总结了其他答案.您可以git pull无错误地执行:

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

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

  • 我怀疑第三行`git reset --hard HEAD`可能是多余的; 我的本地手册页(2.6.3)说第二行中的`reset``git reset --hard origin/master` _"默认为HEAD的所有形式."_
  • 这将覆盖已修改的文件(先前已签入的文件),并将删除未跟踪的文件(从未检入过的文件).正是我在寻找,谢谢!
  • @arichards我认为你的嫌疑人是正确的,但如果第二行无法正常工作(无论如何)第三行可以很好地重置.该解决方案不需要优化.我刚刚总结了其他答案.就这样.感谢您的评论.:)

根据我自己的类似经验,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 checkout --theirs /path/to/file.extension
git pull origin master

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


似乎这里的大多数答案都集中在master分支上; 然而,有时候我在两个不同的地方工作同一个功能分支,我希望一个中的rebase能够反映在另一个中而没有大量的跳跃.

基于RNA的答案和torek对类似问题的回答的组合,我提出了这个非常有效的方法:

git fetch
git reset --hard @{u}

从分支运行它,它只会将本地分支重置为上游版本.

这可以很好地放入git alias(git forcepull)中:

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

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

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

请享用!


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


我刚刚解决了这个问题:

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可能会让你在前几次尝试时遇到麻烦,所以首先要对非关键项目进行实验......


我知道一种更简单,更少痛苦的方法:

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

而已!


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

git rm [file]

然后我能够拉得很好.


这四个命令对我有用.

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

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

git pull origin master

我尝试了很多,但最终成功完成了这些命令.

  • "git branch -D master"删除分支.所以要小心.我更喜欢使用"git checkout origin/master -b <new branch name>"来创建一个带有新名称的新分支,你需要3,4行.还建议使用"git clean -f".

尽管存在最初的问题,但最常见的答案可能会给遇到类似问题但又不想丢失本地文件的人带来问题.例如,请参阅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.


做就是了

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

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


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

git reset origin/master

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


要求:

  1. 跟踪当地的变化,所以这里没有人会失去它们.
  2. 使本地存储库与远程源存储库匹配.

解:

  1. 存储本地更改.
  2. git stash --include-untracked
    git fetch --all
    git clean -fdx
    git reset --hard origin/master
    

我阅读了所有的答案,但我正在寻找一个命令来做到这一点.这就是我做的.为.gitconfig添加了一个git别名

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

运行您的命令

git fp origin master

相当于

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

不要用git reset --hard.这将抹去他们可能完全不受欢迎的变化.代替:

git pull
git reset origin/master
git checkout <file1> <file2> ...

你当然可以使用,git fetch而不是git pull因为它显然不会合并,但如果你通常拉它,继续拉这里是有道理的.

那么这里发生的是git pull 更新您的origin/master引用 ; git reset 将本地分支引用更新为与origin/master相同而不更新任何文件,因此您的签出状态不会更改; 然后根据需要git checkout 将文件恢复到本地分支索引状态.如果在实时和上游主服务器上添加了完全相同的文件,则索引已经与重置后的文件匹配,因此在常见情况下您根本不需要执行此操作git checkout.

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

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

这是还原更改的最佳做法:

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

在引用日志 记录分支和其他参考在本地存储库进行更新.或者简单地说 - reflog您更改历史记录.

因此,提交始终是一个很好的做法.提交附加到reflog,确保您始终可以检索已删除的代码.


如果要以通用方式重置到远程跟踪分支,请使用:

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

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

git fetch
git reset --hard origin/$(git rev-parse --abbrev-ref HEAD)
  • If you find yourself using this frequently add a bash shortcut `alias gplf='git fetch && echo "HEAD was at $(git rev-parse --short HEAD)" && git reset --hard origin/$(git rev-parse --abbrev-ref HEAD)'`

我使用此命令来删除本地文件,阻止我进行拉/合并.不过要小心!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是什么,都会以从空白开始的每一行调用.


我试图在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',然后按Enter)

现在你准备好了.


以上是如何强制”git pull”覆盖本地文件?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>