如何在git pull
上强制覆盖本地文件?
该场景如下:
- 团队成员正在修改我们正在工作的网站的模板
- 他们正在将一些图像添加到图像目录(但是忘记在源代码控制下添加它们)
- 他们通过邮件将图像发送给我
- 我将图像添加到源代码管理下,并将其与其他更改一起推送到GitHub
- 他们无法从GitHub提取更新,因为Git不想覆盖其文件。
这是我得到的错误:
错误:未跟踪的工作树文件“ public / images / icon.gif”将被合并覆盖
如何强制Git覆盖它们? 这个人是设计师-通常我会手工解决所有冲突,因此服务器具有他们只需在计算机上更新的最新版本。
#1楼
像刺猬一样,我认为答案很糟糕。 但是,尽管刺猬的答案可能更好,但我认为它并没有它的优雅。 我发现做到这一点的方法是通过使用已定义策略的“提取”和“合并”。 应该这样做,以便保留本地更改,只要它们不是您要强制覆盖的文件之一即可。
首先提交您的更改
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”是该选项的值。 如果发生冲突,您选择使用“他们的”更改,而不是“您的”更改。
#2楼
看来最好的方法是先这样做:
git clean
要删除所有未跟踪的文件,然后继续执行常规的git pull
...
#3楼
首先,尝试标准方法:
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
在某些情况下可能会失败?
.gitattributes file
自定义规则在.gitattributes中使用
eol=lf
规则可能会导致git通过将某些文本文件中的CRLF行尾转换为LF来修改某些文件更改。如果是这样,您必须提交这些CRLF / LF更改(通过在
git status
查看它们),或尝试:git config core.autcrlf false
以暂时忽略它们。文件系统不兼容
当您使用不支持权限属性的文件系统时。 在示例中,您有两个存储库,一个在Linux / Mac(
ext3
/hfs+
)上,另一个在基于FAT32 / NTFS的文件系统上。你可能注意到了,有两种不同类型的文件系统,所以不支持Unix许可基本上无法重置系统不支持那种权限的文件权限的一个,所以无论怎么
--hard
你尝试一下,git总是检测到一些“变化”。
#4楼
所有这些解决方案的问题在于它们要么太复杂,要么甚至更大的问题在于它们从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
第一条命令获取最新数据。
第二个命令检查是否有任何文件要添加到存储库中,并从本地存储库中删除那些会引起冲突的未跟踪文件。
第三个命令检出所有在本地修改的文件。
最终,我们拉动更新到最新版本,但是这次没有任何冲突,因为回购中不再存在未跟踪的文件,并且所有本地修改的文件已经与存储库中的相同。
#5楼
而不是与git pull
合并,请尝试以下操作:
git fetch --all
其次是:
git reset --hard origin/master
。
#6楼
将索引和标头重置为origin/master
,但不要重置工作树:
git reset origin/master
#7楼
根据我自己的类似经验,上述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
#8楼
而不是做:
git fetch --all
git reset --hard origin/master
我建议您执行以下操作:
git fetch origin master
git reset --hard origin/master
如果您要重置为Origin / master分支,就不需要获取所有的遥控器和分支吗?
#9楼
似乎大多数答案都集中在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}"
请享用!
#10楼
这四个命令对我有用。
git reset --hard HEAD
git checkout origin/master
git branch -D master
git checkout -b master
执行这些命令后进行检查/拉动
git pull origin master
我做了很多尝试,但最终在这些命令上获得了成功。
#11楼
尽管有最初的问题,但是对于有类似问题但又不想丢失其本地文件的用户,最重要的答案可能会引起问题。 例如,请参阅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
。
#12楼
尝试这个:
git reset --hard HEAD
git pull
它应该做您想要的。
#13楼
一种更简单的方法是:
git checkout --theirs /path/to/file.extension
git pull origin master
这将用git上的文件覆盖您的本地文件
#14楼
我总结了其他答案。 您可以执行git pull
而不会出现错误:
git fetch --all
git reset --hard origin/master
git reset --hard HEAD
git clean -f -d
git pull
警告 :此脚本非常强大,因此您可能会丢失所做的更改。
#15楼
要求:
- 跟踪本地更改,因此这里没有人会丢失它们。
- 使本地存储库与远程原始存储库匹配。
解:
- 隐藏本地更改。
用干净的 文件和目录忽略的.gitignore和硬复位 原产地获取 。
git stash --include-untracked git fetch --all git clean -fdx git reset --hard origin/master
#16楼
我知道一种更简单,更轻松的方法:
$ git branch -m [branch_to_force_pull] tmp
$ git fetch
$ git checkout [branch_to_force_pull]
$ git branch -D tmp
而已!
#17楼
做就是了
git fetch origin branchname
git checkout -f origin/branchname // This will overwrite ONLY new included files
git checkout branchname
git merge origin/branchname
因此,您可以避免所有不必要的副作用,例如删除要保留的文件或目录等。
#18楼
您可能会发现此命令有助于丢弃本地更改:
git checkout <your-branch> -f
然后进行清理(从工作树中删除未跟踪的文件):
git clean -f
如果要除去未跟踪文件之外的其他未跟踪目录,请执行以下操作:
git clean -fd
#19楼
奖金:
在谈到之前的答案中的拉取/获取/合并时,我想分享一个有趣且富有成效的技巧,
git pull --rebase
上面的命令是我的Git生命中最有用的命令,它节省了很多时间。
在将新提交的内容推送到服务器之前,请尝试使用此命令,它将自动同步最新的服务器更改(通过访存+合并),并将您的提交内容放在Git日志的顶部。 无需担心手动拉/合并。
在“ git pull --rebase”做什么中找到详细信息? 。
#20楼
我通读了所有答案,但我正在寻找一个命令来执行此操作。 这是我所做的。 为.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
#21楼
我自己通过以下方法解决了这个问题:
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可能会给您带来麻烦,因此,请首先在非关键项目上进行实验...
#22楼
我有同样的问题。 没有人给我这种解决方案,但是对我有用。
我通过以下方法解决了它:
- 删除所有文件。 仅保留
.git
目录。 -
git reset --hard HEAD
-
git pull
-
git push
现在可以了。
#23楼
我有一个类似的问题。 我必须这样做:
git reset --hard HEAD
git clean -f
git pull
#24楼
警告: 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
...
#25楼
唯一对我有用的是:
git reset --hard HEAD~5
这将带您退回五次提交,然后
git pull
通过查找如何撤消Git合并 ,我发现了这一点。
#26楼
我遇到了同样的问题,由于某种原因,即使是git clean -f -d
也不会这样做。 这是为什么:由于某种原因,如果您的文件被Git忽略(我认为是通过.gitignore条目),它仍然会为以后的pull重写而烦恼,但是除非您添加-x
,否则干净不会删除它。
#27楼
我有一个奇怪的情况,无论是git clean
还是git reset
都git clean
。 我必须通过在每个未跟踪的文件上使用以下脚本从git index
删除冲突的文件:
git rm [file]
然后我可以拉得很好。
#28楼
我相信有两种可能的冲突原因,必须分别解决,据我所知,上述答案均未涉及这两种问题:
需要手动删除(更安全)或按照其他答案的建议,通过
git clean -f -d
删除未跟踪的本地文件。不在远程分支上的本地提交也需要删除。 IMO实现此目的最简单的方法是:
git reset --hard origin/master
(用正在处理的任何分支替换“ master”,然后首先运行git fetch origin
)
#29楼
重要提示:如果您进行任何本地更改,它们将会丢失。 无论是否使用--hard
选项,所有尚未推送的本地提交都将丢失。 [*]
如果您有Git 不能跟踪的任何文件(例如,上载的用户内容),这些文件将不会受到影响。
我认为这是正确的方法:
git fetch --all
然后,您有两个选择:
git reset --hard origin/master
或如果您在其他分支机构:
git reset --hard origin/<branch_name>
说明:
git fetch
从远程下载最新版本,而无需尝试合并或重新设置任何内容。
然后git reset
将master分支重置为您刚刚获取的分支。 --hard
选项更改工作树中的所有文件以匹配origin/master
文件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
#30楼
警告,如果您在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}