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


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

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

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

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

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

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

30 5409

30 ответов:

важно: если у вас есть какие-либо изменения, они будут утеряны. С или без --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 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.

некоторые ответы кажутся ужасными. Ужасно в смысле того, что случилось с @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}

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

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
  • первая команда загружает новые данные.

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

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

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

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

я решил это с помощью:

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

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

  • локальные коммиты, которые не находятся на удаленной ветке, также должны быть удалены. ИМО самый простой способ добиться этого-это: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}

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

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

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

или в .gitconfig file:

[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 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

где мы предполагаем другой хранилище и 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. сделайте локальный репозиторий соответствующим удаленному исходному репозиторию.

устранение:

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

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