可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How do I force an overwrite of local files on a git pull
?
The scenario is following:
- A team member is modifying the templates for a website we are working on
- They are adding some images to the images directory (but forgets to add them under source control)
- They are sending the images by mail, later, to me
- I'm adding the images under the source control and pushing them to GitHub together with other changes
- They cannot pull updates from GitHub because Git doesn't want to overwrite their files.
The errors I'm getting are:
error: Untracked working tree file 'public/images/icon.gif' would be overwritten by merge.
How do I force Git to overwrite them? The person is a designer - usually I resolve all the conflicts by hand, so the server has the most recent version that they just needs to update on their computer.
回答1:
Important: If you have any local changes, they will be lost. With or without --hard
option, any local commits that haven't been pushed will be lost.[*]
If you have any files that are not tracked by Git (e.g. uploaded user content), these files will not be affected.
I think this is the right way:
git fetch --all
Then, you have two options:
git reset --hard origin/master
OR If you are on some other branch:
git reset --hard origin/
Explanation:
git fetch
downloads the latest from remote without trying to merge or rebase anything.
Then the git reset
resets the master branch to what you just fetched. The --hard
option changes all the files in your working tree to match the files in origin/master
[*]: It's worth noting that it is possible to maintain current local commits by creating a branch from master
before resetting:
git checkout master git branch new-branch-to-save-current-commits git fetch --all git reset --hard origin/master
After this, all of the old commits will be kept in new-branch-to-save-current-commits
. Uncommitted changes however (even staged), will be lost. Make sure to stash and commit anything you need.
回答2:
Try this:
git reset --hard HEAD git pull
It should do what you want.
回答3:
WARNING: git clean
deletes all your untracked files/directories and can't be undone.
Sometimes just clean -f
does not help. In case you have untracked DIRECTORIES, -d option also needed:
git reset --hard HEAD git clean -f -d git pull
WARNING: git clean
deletes all your untracked files/directories and can't be undone.
回答4:
Like Hedgehog I think the answers are terrible. But though Hedgehog's answer might be better, I don't think it is as elegant as it could be. The way I found to do this is by using "fetch" and "merge" with a defined strategy. Which should make it so that your local changes are preserved as long as they are not one of the files that you are trying to force an overwrite with.
First do a commit of your changes
git add * git commit -a -m "local file server commit message"
Then fetch the changes and overwrite if there is a conflict
git fetch origin master git merge -s recursive -X theirs origin/master
"-X" is an option name, and "theirs" is the value for that option. You're choosing to use "their" changes, instead of "your" changes if there is a conflict.
回答5:
Instead of doing:
git fetch --all git reset --hard origin/master
I'd advise doing the following:
git fetch origin master git reset --hard origin/master
No need to fetch all remotes and branches if you're going to reset to the origin/master branch right?
回答6:
It looks like the best way is to first do:
git clean
To delete all untracked files and then continue with the usual git pull
...
回答7:
Warning, doing this will permanently delete your files if you have any directory/* entries in your gitignore file.
Some answers seem to be terrible. Terrible in the sense of what happened to @Lauri by following David Avsajanishvili suggestion.
Rather (git > v1.7.6):
git stash --include-untracked git pull
Later you can clean the stash history.
Manually, one-by-one:
$ git stash list stash@{0}: WIP on : ... stash@{1}: WIP on : ... $ git stash drop stash@{0} $ git stash drop stash@{1}
Brutally, all-at-once:
$ git stash clear
Of course if you want to go back to what you stashed:
$ git stash list ... $ git stash apply stash@{5}
回答8:
You might find this command helpful to throw away local changes:
git checkout -f
And then do a cleanup (removes untracked files from the working tree):
git clean -f
If you want to remove untracked directories in addition to untracked files:
git clean -fd
回答9:
Instead of merging using git pull
, try git fetch --all
followed by git reset --hard origin/master
.
回答10:
The problem with all these solutions is that they are all either too complex, or, an even bigger problem, is that they remove all untracked files from the web server, which we don't want since there are always needed configuration files which are on the server and not in the Git repository.
Here is the cleanest solution which we are using:
# 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
The first command fetches newest data.
The second command checks if there are any files which are being added to the repository and deletes those untracked files from the local repository which would cause conflicts.
The third command checks-out all the files which were locally modified.
Finally we do a pull to update to the newest version, but this time without any conflicts, since untracked files which are in the repo don't exist anymore and all the locally modified files are already the same as in the repository.
回答11:
The only thing that worked for me was:
git reset --hard HEAD~5
This will take you back five commits and then with
git pull
I found that by looking up how to undo a Git merge.
回答12:
I had the same problem. No one gave me this solution, but it worked for me.
I solved it by:
- Deleting all the files. Leave just the .git directory.
git reset --hard HEAD
git pull
git push
Now it works.
回答13:
First of all, try the standard way:
git reset HEAD --hard # Remove all not committed changes
If above won't help and you don't care about your untracked files/directories (make the backup first just in case), try the following simple steps:
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
This will REMOVE all git files (excempt .git/
dir, where you have all commits) and pull it again.
Why git reset HEAD --hard
could fail in some cases?
Custom rules in .gitattributes file
Having eol=lf
rule in .gitattributes could cause git to modify some file changes by converting CRLF line-endings into LF in some text files.
If that's the case, you've to commit these CRLF/LF changes (by reviewing them in git status
), or try: git config core.autcrlf false
to temporary ignore them.
File system incompability
When you're using file-system which doesn't support permission attributes. In example you have two repositories, one on Linux/Mac (ext3
/hfs+
) and another one on FAT32/NTFS based file-system.
As you notice, there are two different kind of file systems, so the one which doesn't support Unix permissions basically can't reset file permissions on system which doesn't support that kind of permissions, so no matter how --hard
you try, git always detect some "changes".
回答14:
I had a similar problem. I had to do this:
git reset --hard HEAD git clean -f git pull
回答15:
Based on my own similar experiences, the solution offered by Strahinja Kustudic above is by far the best. As others have pointed out, simply doing hard reset will remove all the untracked files which could include lots of things that you don't want removed, such as config files. What is safer, is to remove only the files that are about to be added, and for that matter, you'd likely also want to checkout any locally-modified files that are about to be updated.
That in mind, I updated Kustudic's script to do just that. I also fixed a typo (a missing ' in the original).
#/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
回答16:
I summarized other answers. You can execute git pull
without errors:
git fetch --all git reset --hard origin/master git reset --hard HEAD git clean -f -d git pull
Warning: This script is very powerful, so you could lose your changes.
回答17:
I believe there are two possible causes of conflict, which must be solved separately, and as far as I can tell none of the above answers deals with both:
Local files that are untracked need to be deleted, either manually (safer) or as suggested in other answers, by git clean -f -d
Local commits that are not on the remote branch need to be deleted as well. IMO the easiest way to achieve this is with: git reset --hard origin/master
(replace 'master' by whatever branch you are working on, and run a git fetch origin
first)
回答18:
An easier way would be to:
git checkout --theirs /path/to/file.extension git pull origin master
This will override your local file with the file on git
回答19:
I had the same problem and for some reason, even a git clean -f -d
would not do it. Here is why: For some reason, if your file is ignored by Git (via a .gitignore entry, I assume), it still bothers about overwriting this with a later pull, but a clean will not remove it, unless you add -x
.
回答20:
Bonus:
In speaking of pull/fetch/merge in the above answers, I would like to share an interesting and productive trick,
git pull --rebase
This above command is the most useful command in my git life which saved a lots of time.
Before pushing your newly commit to server, try this command and it will automatically sync latest server changes (with a fetch + merge) and will place your commit at the top in git log. No need to worry about manual pull/merge.
Find details at: http://gitolite.com/git-pull--rebase
回答21:
It seems like most answers here are focused on the master
branch; however, there are times when I'm working on the same feature branch in two different places and I want a rebase in one to be reflected in the other without a lot of jumping through hoops.
Based on a combination of RNA's answer and torek's answer to a similar question, I've come up with this which works splendidly:
git fetch git reset --hard @{u}
Run this from a branch and it'll only reset your local branch to the upstream version.
This can be nicely put into a git alias (git forcepull
) as well:
git config alias.forcepull "!git fetch ; git reset --hard @{u}"
Or, in your .gitconfig
file:
[alias] forcepull = "!git fetch ; git reset --hard @{u}"
Enjoy!
回答22:
I just solved this myself by:
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
where the last command gives a list of what your local changes were. Keep modifying the "tmp" branch until it is acceptable and then merge back onto master with:
git checkout master && git merge tmp
For next time, you can probably handle this in a cleaner way by looking up "git stash branch" though stash is likely to cause you trouble on the first few tries, so do first experiment on a non-critical project...
回答23:
I have a strange situation that neither git clean
or git reset
works. I have to remove the conflicting file from git index
by using the following script on every untracked file:
git rm [file]
Then I am able to pull just fine.
回答24:
These four commands work for me.
git reset --hard HEAD git checkout origin/master git branch -D master git checkout -b master
To check/pull after executing these commands
git pull origin master
I tried a lot but finally got success with these commands.
回答25:
Despite the original question, the top answers can cause problems for people who have a similar problem, but don't want to lose their local files. For example, see Al-Punk and crizCraig's comments.
The following version commits your local changes to a temporary branch (tmp
), checks out the original branch (which I'm assuming is master
) and merges the updates. You could do this with stash
, but I've found it's usually easier to simply use the branch / merge approach.
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
where we assume the other repository is origin master
.
回答26:
Just do
git fetch origin branchname git checkout -f origin/branchname // This will overwrite ONLY new included files git checkout branchname git merge origin/branchname
So you avoid all unwanted side effects, like deleting files or directories you wanted to keep, etc.
回答27:
Reset the index and the head to origin/master
, but do not reset the working tree:
git reset origin/master
回答28:
Requirements:
- Track local changes so no-one here ever loses them.
- Make the local repository match the remote origin repository.
Solution:
- Stash the local changes.
Fetch with a clean of files and directories ignoring .gitignore and hard reset to origin.
git stash --include-untracked git fetch --all git clean -fdx git reset --hard origin/master
回答29:
I know a much more easier and less painful method:
$ git branch -m [branch_to_force_pull] tmp $ git fetch $ git checkout [branch_to_force_pull] $ git branch -D tmp
That's it!
回答30:
I read through all the answers but I was looking for a single command to do this. Here is what I did. Added a git alias to .gitconfig
[alias] fp = "!f(){ git fetch ${1} ${2} && git reset --hard ${1}/${2};};f"
Run your command as
git fp origin master
equivalent to
git fetch origin master git reset --hard origin/master