Как заставить "git pull" перезаписывать локальные файлы?

Как принудительно перезаписать локальные файлы на git pull?

сценарий следующий:

  • член команды изменяет шаблоны для веб-сайта, над которым мы работаем
  • они добавляют некоторые изображения в каталог изображений (но забывает добавить их под контролем источника)
  • они посылают изображения по почте, позже, мне
  • я добавляю изображения под контролем источника и нажимаю их на GitHub вместе с другие изменения
  • они не могут извлекать обновления из GitHub, потому что Git не хочет перезаписывать свои файлы.

это ошибка, которую я получаю:

error: Untracked working tree file 'public/images/icon.gif' would be overwritten by merge

Как заставить Git перезаписать их? Человек-дизайнер-обычно я разрешаю все конфликты вручную, поэтому сервер имеет самую последнюю версию, которую им просто нужно обновить на своем компьютере.

30 ответов


важно: если у вас есть какие-либо изменения, они будут утеряны. С или без --hard опция, любые локальные коммиты, которые не были нажаты, будут потеряны.[*]

если у вас есть какие-либо файлы не отслеживается Git (например, загруженный пользовательский контент), эти файлы не будут затронуты.


я думаю, что это правильно:

git fetch --all

затем, у вас есть два варианта:

git reset --hard origin/master

или если вы на какая-то другая ветвь:

git reset --hard origin/<branch_name>

объяснение:

git fetch загружает последнюю версию с пульта дистанционного управления, не пытаясь объединить или перебазировать что-либо.

тут git reset сбрасывает главную ветку на то, что вы только что получили. The --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 reset --hard HEAD
git pull

Он должен делать то, что вы хотите.


предупреждение: 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
...

Как Ежик я думаю, что ответы ужасны. Но хотя ответ ежика может быть лучше, я не думаю, что это так элегантно, как могло бы быть. Я нашел способ сделать это, используя "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 fetch --all
git reset --hard origin/master

Я бы посоветовал сделать следующее:

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

нет необходимости извлекать все пульты и ветви, если вы собираетесь сбросить в исходную / главную ветвь правильно?


похоже, что лучший способ-сначала сделать:

git clean

чтобы удалить все неотслеженные файлы, а затем продолжить с обычным git pull...


предупреждение, это навсегда удалить ваши файлы, если у вас есть каталог/* записи в файла.gitignore

некоторые ответы кажутся ужасными. Страшная, в смысле, что случилось с @Лаури по следующим Дэвид предложение Avsajanishvili.

скорее (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}

вы можете найти эту команду полезной, чтобы выбросить локальные изменения:

git checkout <your-branch> -f

а затем выполните очистку (удаляет неотслеженные файлы из рабочего дерева):

git clean -f

Если вы хотите удалить неотслеживаемые каталоги в дополнение к неотслеживаемым файлам:

git clean -fd

вместо слияния с git pull, попробуйте это:

git fetch --all

затем:

git reset --hard origin/master.


единственное, что работал для меня было:

git reset --hard HEAD~5

это вернет вам пять коммитов, а затем с

git pull

Я нашел это, посмотрев вверх как отменить слияние Git.


проблема со всеми этими решениями заключается в том, что все они либо слишком сложны, либо, что еще большая проблема, в том, что они удаляют все неотслеженные файлы с веб-сервера, чего мы не хотим, так как всегда есть необходимые файлы конфигурации, которые находятся на сервере, а не в репозитории 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 }'`
do
    rm -f -- "$file"
done

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

# Finally pull all the changes
# (you could merge as well e.g. 'merge origin/master')
git pull
  • первая команда загружает новые данные.

  • второй команда проверяет наличие файлов, добавляемых в репозиторий, и удаляет из локального репозитория непрослеженные файлы, которые могут вызвать конфликты.

  • третья команда проверяет все файлы, которые были изменены локально.

  • наконец, мы делаем pull для обновления до последней версии, но на этот раз без каких-либо конфликтов, так как неотслеженные файлы, которые находятся в репо, больше не существуют, и все локально измененные файлы уже то же самое, что и в репозитории.


у меня была та же проблема. Никто не дал мне это решение, но оно сработало для меня.

я решил ее:

  1. удаление всех файлов. Оставь только то .каталог git.
  2. git reset --hard HEAD
  3. git pull
  4. git push

Теперь все работает.


прежде всего, попробуйте стандартный способ:

git reset HEAD --hard # Remove all not committed changes

если выше не поможет и вы не заботитесь о свой неотслеживаемый файлы/каталоги (сделайте резервную копию на всякий случай), попробуйте следующие простые шаги:

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 (excempt .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. incompability файловой системы

    когда вы используете файловую систему, которая не поддерживает атрибутами разрешения. В примере вы есть два репозитория, один на Linux / Mac (ext3/hfs+) и еще один в файловой системе на основе FAT32/NTFS.

    как вы заметили, существует два вида файловых систем, так что не поддерживает разрешений Unix в принципе не можем восстановить доступ к файлам системы, которая не поддерживает такие разрешения, так как ни --hard вы пытаетесь, git всегда обнаруживает некоторые "изменения".


У меня была похожая проблема. Я должен был сделать это:

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

я суммировал другие ответы. Вы можете выполнить git pull без ошибок:

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

предупреждение: этот скрипт очень мощный, поэтому вы можете потерять свои изменения.


основываясь на моем собственном подобном опыте, решение, предложенное Страхиньей Кустудичем выше, безусловно, лучшее. Как указывали другие, просто выполнение жесткого сброса удалит все неотслеженные файлы, которые могут включать в себя множество вещей, которые вы не хотите удалять, например файлы конфигурации. Что безопаснее, это удалить только файлы, которые будут добавлены, и, если на то пошло, вы, вероятно, также захотите проверить любые локально измененные файлы, которые будут усовершенствованный.

что в виду, я обновил сценарий Кустудича, чтобы сделать именно это. Я также исправил опечатку (отсутствует ' в оригинале).

#/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 }'`
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 }'`
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

бонус:

говоря о pull / fetch / merge в предыдущих ответах, я хотел бы поделиться интересным и продуктивным трюком,

git pull --rebase

эта команда выше-самая полезная команда в моей жизни Git, которая сэкономила много времени.

прежде чем нажимать новую фиксацию на сервер, попробуйте эту команду, и она автоматически синхронизирует последние изменения сервера (с fetch + merge) и разместит вашу фиксацию на сверху в журнале Git. Нет необходимости беспокоиться о ручном вытягивании/слиянии.

найти детали в что делает "git pull --rebase"?.


Я считаю, что существуют две возможные причины конфликта, которые должны быть решены отдельно, и, насколько я могу судить, ни один из приведенных выше ответов не касается обоих:

  • локальные файлы, которые не отслеживаются, должны быть удалены вручную (безопаснее) или, как предложено в других ответах,git clean -f -d

  • локальные коммиты, которые не находятся в удаленной ветви, также должны быть удалены. IMO самый простой способ достичь этого-с помощью:git reset --hard origin/master (заменить 'master' в какой бы отрасли вы ни работали, и запустите git fetch origin первая)


более простым способом было бы:

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

это переопределит ваш локальный файл с файлом на git


похоже, что большинство ответов здесь сосредоточены на master ветка; однако, бывают случаи, когда я работаю над одной и той же веткой функции в двух разных местах, и я хочу, чтобы ребаз в одном отражался в другом без большого количества прыжков через обручи.

на основе сочетания ответ РНК и ответ торека на аналогичный вопрос, я придумал это работает великолепно:

git fetch
git reset --hard @{u}

запустите это из ветки и это только сбросит вашу локальную ветвь до версии upstream.

это можно красиво поместить в псевдоним git (git forcepull), а также:

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

или в :

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

наслаждайтесь!


у меня была такая же проблема и по каким-то причинам, даже git clean -f -d не сделал бы этого. Вот почему: по какой-то причине, если ваш файл игнорируется Git (через a .запись 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", хотя stash, вероятно, вызовет у вас проблемы с первых нескольких попыток, поэтому сделайте первый эксперимент над некритическим проектом...


у меня странная ситуация, что ни git clean или git 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

Я много пробовал, но, наконец, добился успеха с этими командами.


несмотря на оригинальный вопрос, лучшие ответы могут вызвать проблемы для людей, которые имеют аналогичную проблему, но не хотят терять свои локальные файлы. Например, см. комментарии 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

где мы предполагаем другой хранилище is 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 branch -m [branch_to_force_pull] tmp
$ git fetch
$ git checkout [branch_to_force_pull]
$ git branch -D tmp

вот именно!


Я прочитал все ответы, но я искал одну команду, чтобы сделать это. Вот что я сделал. Добавлен псевдоним git .gitconfig хранит настройки

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

выполните команду как

git fp origin master

эквивалентно

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

требования:

  1. отслеживание локальных изменений, так что никто здесь никогда не теряет их.
  2. сделать локальный репозиторий соответствующим удаленному репозиторию origin.

устранение:

  1. притон локальные изменения.
  2. Fetch С очистить of файлы и каталоги игнорировать .gitignore и перезагрузка к происхождения.

    git stash --include-untracked
    git fetch --all
    git clean -fdx
    git reset --hard origin/master