it-swarm.com.ru

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

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

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

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

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

ошибка: неотслеживаемый файл рабочего дерева 'public/images/icon.gif' будет перезаписан слиянием

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

5771
Jakub Troszok

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

Попробуй это:

git reset --hard HEAD
git pull

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

808
Travis Reeder

ВНИМАНИЕ: 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
...
409
David Avsajanishvili

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

Сначала сделайте коммит ваших изменений

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

Затем извлеките изменения и перепишите, если есть конфликт

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

«-X» - это имя опции, а «их» - значение для этой опции. Вы решаете использовать «свои» изменения, а не «свои», если есть конфликт.

347
Richard Kersey

Вместо того, чтобы делать:

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

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

git fetch Origin master
git reset --hard Origin/master

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

251
Johanneke

Похоже, лучше всего сначала сделать:

git clean

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

125
Jakub Troszok

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

Некоторые ответы кажутся ужасными. Ужасно в смысле того, что случилось с @Lauri, следуя предложению Давида Авсаджанишвили.

Скорее (git> v1.7.6):

git stash --include-untracked
git pull

Позже вы можете очистить тайник истории.

Вручную, один за другим:

$ git stash list
[email protected]{0}: WIP on <branch>: ...
[email protected]{1}: WIP on <branch>: ...

$ git stash drop [email protected]{0}
$ git stash drop [email protected]{1}

Жестоко, все сразу:

$ git stash clear

Конечно, если вы хотите вернуться к тому, что вы спрятали:

$ git stash list
...
$ git stash apply [email protected]{5}
102
Hedgehog

Эта команда может оказаться полезной для удаления локальных изменений:

git checkout <your-branch> -f

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

git clean -f

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

git clean -fd
88
Vishal

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

git fetch --all

с последующим:

git reset --hard Origin/master.

82
Lloyd Moore

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

git reset --hard HEAD~5

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

git pull

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

55
Chris BIllante

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

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

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

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

51
Strahinja Kustudic

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

Я решил это:

  1. Удалить все файлы. Оставьте только каталог .git.
  2. git reset --hard HEAD
  3. git pull
  4. git Push

Теперь это работает.

39
John John Pichler

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

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

34
kenorb

Бонус:

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

git pull --rebase

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

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

Найти подробности в Что делает "git pull --rebase"?.

33
Sazzad Hissain Khan

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

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

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

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

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

27
Robert Moon

Основываясь на моем собственном подобном опыте, решение, предложенное Strahinja Kustudic выше, является безусловно лучшим. Как уже отмечали другие, просто сделать hard reset удалит все неотслеживаемые файлы, которые могут включать в себя множество вещей, которые вы не хотите удалять, такие как файлы конфигурации. Более безопасным является удаление только тех файлов, которые будут добавлены, и в этом отношении вы, вероятно, также захотите извлечь любые локально-модифицированные файлы, которые будут обновлены.

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

#/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
26
Rolf Kaiser

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

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

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

23
tiho

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

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

Это заменит ваш локальный файл с файлом на git

20
maximus 69

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

Основываясь на комбинации ответа РНК и ответа Торека на похожий вопрос , я придумала это, которое прекрасно работает:

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}"

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

20
JacobEvelyn

У меня была такая же проблема, и по какой-то причине даже git clean -f -d этого не сделал. И вот почему: по какой-то причине, если ваш файл игнорируется Git (через запись .gitignore, я полагаю), он все еще беспокоится о перезаписи этого с более поздним pull , но clean не будет удалите его, если только вы не добавите -x.

19
Tierlieb

Я просто решил это сам:

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

18
Simon B.

У меня странная ситуация, когда ни git clean, ни git reset не работают. Я должен удалить конфликтующий файл из git index, используя следующий скрипт для каждого неотслеживаемого файла:

git rm [file]

Тогда я могу тянуть просто отлично.

17
Chen Zhang

Я знаю гораздо более простой и менее болезненный метод:

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

Это оно!

16
ddmytrenko

Эти четыре команды работают для меня.

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

Чтобы проверить/вытащить после выполнения этих команд

git pull Origin master

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

13
vishesh chandra

Просто делать

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

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

12
user2696128

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

Сбросьте индекс и заголовок на Origin/master, но не сбрасывайте рабочее дерево:

git reset Origin/master
11
user811773

Требования:

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

Решение:

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

    git stash --include-untracked
    git fetch --all
    git clean -fdx
    git reset --hard Origin/master
    
9
vezenkov

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

[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
9
Venkat Kotra

Не используйте git reset --hard. Это сотрет их изменения, которые могут быть совершенно нежелательными. Вместо:

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

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

Итак, что здесь происходит, это то, что git pull обновляет вашу исходную/основную ссылку ; git reset обновляет вашу локальную ссылку на ветвь on так, чтобы она совпадала с Origin/master без обновления каких-либо файлов, поэтому ваше состояние извлечения остается неизменным; затем git checkout возвращает файлы в состояние индекса вашей локальной ветви по мере необходимости. В тех случаях, когда один и тот же файл был добавлен в прямом эфире и на главном канале, индекс уже соответствует файлу после сброса, поэтому в общем случае вам вообще не нужно делать git checkout.

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

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

Это лучшая практика для отмены изменений:

  • git commit Зафиксируйте свои поэтапные изменения, чтобы они были сохранены в reflog (см. ниже)
  • git fetch извлекать последние вышестоящие изменения
  • git reset --hard Origin/master Хард ресет в основную ветку Origin

reflogзаписывает ветки и другие ссылки, обновляемые в локальном хранилище. Или проще говоря - reflog - это история ваших изменений.

Так что это всегда отличная практика. Коммиты добавляются в reflog, что гарантирует, что у вас всегда будет возможность получить удаленный код.

7
Jordan Georgiev

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

5
Glutexo

Я пытался использовать ветку Material2 на Angular2-Webpack-Starter, и у меня было очень много времени. Это был единственный способ загрузить и использовать эту ветку.

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)

Теперь вы готовы.

5
Helzgate

В Windows выполните эту единственную команду:

git fetch --all & git reset --hard Origin/master
3
Luca C.

Вы можете игнорировать этот файл с файлом в базовой папке вашего проекта:

.gitignore

public/images/*

Затем извлеките изменения и затем удалите эту строку из файла gitignore.

3
Daniel Gaytán

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

0
Suge

1: сброс до предыдущего коммита

git reset --hard HEAD

2: Удалить неотслеживаемые файлы

git clean -f

3: Потяните коммиты

git pull

Источники:

0
abhijithvijayan

если вы хотите выполнить общий сброс в ветке удаленного отслеживания, используйте:

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

если вы хотите сбросить локальные изменения:

git fetch
git reset --hard Origin/$(git rev-parse --abbrev-ref HEAD)
0
warch