Git pull не обновляет файлы

Обновлено: 07.07.2024

Я делаю git pull из библиотеки с открытым исходным кодом, мне все равно, какая у меня локальная копия, я просто хочу обновить ее версией источника.

то есть. это может сдуть мои локальные изменения.

3 ответа

Это должно сработать:

Это проверяет ветку удаленного отслеживания в заголовке без имени, тогда вы можете посмотреть и убедиться, что вы счастливы. Всякий раз, когда вы хотите (даже после изменений или фиксации) вторая проверка git помечает ваше текущее дерево как name_of_branch, даже если для этого нужно удалить старое name_of_branch.

Редактировать: «Какой сумасшедший синтаксис командной строки»

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

  • git fetch извлекает все обновления, которые произошли на сервере origin с момента последнего запуска. Git отделяет выборку с сервера от обновления, слияния и т. д. любых ваших веток . Все ветви с именем origin/XXX являются вашими самыми последними версиями того, что находится на сервере. Это не удаленные ветви , а удаленные ветви отслеживания , локальные ветви, которые отслеживают удаленные ветви. Когда вы делаете git fetch , вы обновляете их, не затрагивая ни одну из своих веток. Когда вы делаете git merge , git rebase и и так далее, вы используете выбранную версию, без , получая более свежую копию с сервера. Это означает, что вы можете контролировать, когда выполняются сетевые запросы (если вы не всегда подключены к серверу), и вы можете «получить» снимок сервера, а затем объединиться на досуге. В случае сомнений сначала выполните git fetch .
  • git checkout origin/name_of_branch git checkout делает две вещи. Он обновляет ваши файлы для этой ветви и устанавливает HEAD для этой ветви. Вещи файлов - это то, что вы ожидаете. Вещи HEAD означают, что когда вы делаете коммиты, они добавляются в конец ветви, которая HEAD указывает на. Итак, checkout выполняет вывод - пишет правильные версии файлов и готовится к вводу - готовится хранить коммиты, которые вы собираетесь делать, в нужном месте. Если вы извлекаете ветку с именем foo , ваше дерево переходит в состояние, сохраненное в foo , и следующие сделанные вами коммиты будут добавлены в foo . В случае origin\xyz вы не можете записать свои изменения в origin - они отслеживают, что находится на сервере origin , и не могут быть зафиксированы напрямую. Таким образом, извлечение обновляет файлы и устанавливает HEAD в ничто - безымянная ветвь. Это останавливает вас от случайной фиксации вашего вновь извлеченного материала обратно в предыдущую ветку, которую вы использовали, и на самом деле вы будете сильно обескуражены коммитом git, пока вы не получите ветку назначения.
  • git checkout -B name_of_branch Как обычно, , когда git делает две разные вещи с помощью одной команды, обе они могут быть настроены отдельно . Итак, вторая часть того, что делает checkout , устанавливает HEAD в ветку, которую вы хотите зафиксировать, это может быть новая ветка, а не ветка, которую вы проверяете, если вы используете -B опция. Поэтому git checkout -B new_stuff old_stuff установит все ваши файлы в состояние в old_stuff , но вы готовы написать свои коммиты в новую ветку new_stuff . Это обычная задача, которая избавляет вас от проверки ветви и ее разветвления в два этапа. Теперь почти все аргументы для мерзавцаКоманды могут быть опущены, и git сделает самую очевидную вещь . В этом случае создается новая ветка на основе той, на которой вы находитесь , а не та, которую вы хотите оформить. Итак, git берет неназванную ветвь, в которой вы находитесь, и создает новую ветку с именем name_of_branch , которую вы можете начать фиксировать. Обратите внимание, что буква «В» в верхнем регистре означает «сила». Если вы используете "-b", git откажется перезаписывать уже существующую ветку. С "-B" он будет выполняться без предупреждения или подтверждения.

Решение для коленного рывка : git reset --hard origin/master

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

Команда безопаснее немного сложнее набрать: git checkout -B master origin/master

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

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

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

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

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

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

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

Сначала запустите выборку, чтобы обновить все ссылки origin/<branch> до последних:

Сделайте резервную копию вашей текущей ветки:

Тогда у вас есть два варианта:

ИЛИ Если вы находитесь в другой ветке:

Пояснение:

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

Затем git reset сбрасывает главную ветвь на то, что вы только что выбрали. Параметр --hard изменяет все файлы в вашем рабочем дереве, чтобы они соответствовали файлам в origin/master

Поддерживать текущие локальные коммиты

[*] : Стоит отметить, что можно поддерживать текущие локальные коммиты, создав ветвь из master перед сбросом:

После этого все старые коммиты будут храниться в new-branch-to-save-current-commits .

Незавершенные изменения

Однако незафиксированные изменения (даже поэтапные) будут потеряны. Не забудьте спрятать и зафиксировать все, что вам нужно. Для этого вы можете запустить следующее:

А затем повторно применить эти незафиксированные изменения:

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

ВНИМАНИЕ: git clean удаляет все неотслеживаемые файлы / каталоги и не может быть отменено.

Иногда просто clean -f не помогает. Если у вас нет отслеживаемых КАТАЛОГОВ, также необходима опция -d:

ВНИМАНИЕ: git clean удаляет все неотслеживаемые файлы / каталоги и не может быть отменено.

Сначала рассмотрите возможность использования флага -n ( --dry-run ). Это покажет вам, что будет удалено без фактического удаления ничего:

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

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

Затем загрузите изменения и перезапишите их, если возникнет конфликт.

-X - это имя параметра, а theirs - значение для этого параметра. Вы решили использовать изменения their (другой вариант - ours изменения) в случае конфликта.

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

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

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

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

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

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

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

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

Вручную, по одному:

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

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

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

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

Вместо слияния с git pull попробуйте следующее:

git reset --hard origin/master .

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

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

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

Вот самое чистое решение, которое мы используем:

Первая команда извлекает самые свежие данные.

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

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

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

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

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

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

Бонус :

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

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

У меня была аналогичная проблема. Пришлось сделать вот что:

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

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

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

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

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

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

Запустите это из ветки, и вы сбросите только локальную ветку до исходной версии.

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

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

Или в вашем файле .gitconfig :

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

Из того, что я понимаю, "git pull" делает выборку и слияние. Для проекта iOS у меня есть настройки, настроенные с настройками распространения (сертификаты, профили подготовки и т.д.). Однако, когда на главной ветке, когда я делаю git pull и git log , я вижу, что git-коммиты обновлены с последним фиксацией из удаленной основной ветки. Но git diff все еще показывает, что мой файл pbxproj отличается (т.е. с профилированными строками профиля и т.д., которые я настроил локально).

Чтобы быть ясным, это идеально для меня, потому что я хочу только изменения кода и не нужно связываться с настройкой профилей распределения и подготовки каждый раз, когда я обновляю ветку непосредственно перед выпуском на производство. Но я также хочу понять, как слияние git. Я ожидал, что git будет объединять файлы, которые я изменил локально, и/или указать конфликт. Но такого не происходит.

Примечание. Я знаю "обновление силы", чтобы сделать мой локальный мастер похожим на удаленный, но вы хотите понять разницу между этим и обычным слиянием.

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

Обновление - я понял, что на самом деле я не ответил "почему":

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

Но ваш worktree (незафиксированные локальные изменения) не получает такой защиты. Если git должен был объединить изменения, и результат не был тем, что вы хотели, вы не могли бы легко "отступить" к тому, что у вас было раньше.

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

Из того, что я понимаю, "git pull" делает выборку и слияние.

Это правильно. Точнее, git pull фактически запускает git fetch , а затем запускает git merge . Вернее, раньше это делалось буквально, в прежние времена; в прошлом году или около того, Git был изменен, чтобы сделать git pull более быстрым, выполняя шаги извлечения и слияния внутри, вместо того, чтобы запускать отдельные команды, когда это возможно, - и вы также можете сказать, что он делает git rebase вместо git merge , и там некоторые другие угловые случаи. Но по существу, pull = fetch + merge.

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

получать

Шаг выборки является более простым: ваш Git вызывает еще один Git. У вашего Git и их Git есть небольшая беседа, в которой их Git сообщает вашему Git о любых новых коммитах, которые у них есть, и что вы этого не делаете. Ваша Git загружает эти новые коммиты в ваш репозиторий, так что у вас есть фиксации сейчас; а затем ваш Git устанавливает ваши имена имен удаленных треков, такие как origin/master чтобы запомнить их Git- master и так далее. (Когда git pull запускает git fetch , это может ограничить выбор Git. В очень старых версиях это даже запрещает Git обновлять ваш origin/master и т.п. Modern Git устраняет эту последнюю бесполезную особенность.)

Пока вы не усложняете это самостоятельно (добавив refspecs или различные флаги выборки), все, что есть для извлечения. Это часть слияния, которая остается сложной. Сделав выборку, git pull теперь запускает git merge и здесь все становится немного сложным.

сливаться

Цель слияния - это легкая часть: Git начинается с того, что вы работаете и совершаете коммиты, а кто-то еще работает и совершает коммиты. Если мы нарисуем те коммиты с более ранними фиксациями влево, а затем совершим движение вправо, давая им простые однобуквенные имена вместо их реальных непонятных идентификаторов хеширования Gitty, мы получаем что-то вроде этого:

Здесь E - ваша последняя фиксация в вашем филиале. Его родителем является commit D ; D является C ; и так далее. Commit H - их последняя фиксация, которую вы только что внесли через git fetch . H является G , родителем которого является F , родителем которого является B Мы можем видеть, что эти две линии развития происходили параллельно, начиная с общей точки - базы слияния - фиксации B

То, что git merge делает для этого случая, - это запустить, по сути, две команды git diff . Первый узнает, что вы изменили:

Второй diff узнает, что они изменили:

Git может комбинировать эти два набора различных изменений, если они не конфликтуют друг с другом. Вернее, до тех пор, пока Гит не думает, что они конфликтуют, Гит не знает, он просто делает много предположений о линейных отличиях от git diff . Успешно (возможно) объединив изменения, Git применяет комбинированные изменения к снимку в базе слияния для создания нового моментального снимка и совершает слияние с двумя родителями:

Создание нового объединения слиянием приводит к тому, что имя ветки, branch , указывает на новую фиксацию, так же, как делает новый обычный коммит.

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

Не все слияния являются истинными слияниями

Предположим, что вы запускаете git fetch (возможно, через git pull ), и ничего не изменилось, так что у вас есть:

Затем, не выполнив никаких действий и не совершив никаких коммитов, вы снова запустите git fetch , только на этот раз они проделали определенную работу и сделали некоторые коммиты:

Если вы теперь попросите Git объединить вашу работу (или работу) с их работой, Git найдет базу слияния, как обычно, но обнаружите, что база слияния является самой фиксацией E Очевидно, что отличная фиксация E против себя не нашла изменений. Git может пойти дальше и построить новую транзакцию слияния в любом случае, комбинируя изменения с некоторыми изменениями, чтобы получить:

где моментальный снимок в H точно совпадает с моментальным снимком в G Но по умолчанию для git merge не стоит беспокоиться. Merge обнаруживает это как операцию быстрой перемотки вперед и вместо этого не выполняет глагол to-merge, а не делает фиксацию прилагательного-слияния. Вместо того, чтобы делать новую фиксацию H , Git просто переместит ветвь имени branch вперед:

и проверьте фиксацию G чтобы G снимок заполнил индекс и рабочее дерево.

Git называет это быстрым слиянием, но не происходит слияния! Быстрая пересылка - это просто операция над именем ветки. В конечном итоге не осталось следа, что это произошло, поэтому Git позволяет запретить "слияние" быстрого слияния. Тем не менее, для локальных веток, которые соответствуют именам удалённого отслеживания, такого рода вещи на самом деле чрезвычайно часто, что вы хотите в любом случае, поэтому это Git по умолчанию.

Если вы хотите получше узнать те части Git, про которые раньше боялись спросить, то этот список для вас. Тут собраны наиболее типичные ситуации и способы их решения как из личного опыта автора, так и собранные по всему Интернету.

Ошибка в комментарии к коммиту

git commit --amend

Как отменить последний коммит?

Можно использовать git reset , вот так:

git reset --hard HEAD

1 означает один коммит до HEAD, т.е. до текущего положения. Стоит заметить, что это «ядерный» способ, который отменит все изменения. Если вам нужно сохранить всё, что вы сделали, но еще не успели закоммитить, используйте:

git reset --soft HEAD

Удалить ветку на сервере

git push origin --delete имя_ветки

В чём разница между «git pull» и «git fetch»?

git pull — это, по сути, git fetch , после которого сразу же следует git merge . git fetch получает изменения с сервера и сохраняет их в refs/remotes/ . Это никак не влияет на локальные ветки и текущие изменения. А git pull вливает все эти изменения в локальную копию.

Как отменить «git add» до коммита?

Вы выполнили git add имя_файла случайно и хотите отменить добавление файла. Если коммит ещё не был сделан, то поможет:

git reset имя_файла

Как разрешать конфликты слияния?

Используйте программу git mergetool , которая предоставляет удобный интерфейс для разрешения конфликтов.

Удалить все локальные файлы и директории, которые не отслеживает Git, из вашей текущей копии

Осторожно! Лучше сделайте перед этим бэкап.

Клонировать все ветки с сервера

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

Можно использовать git checkout origin/имя_ветки , чтобы посмотреть на нужную ветку. Или git checkout -b имя_ветки origin/имя_ветки , чтобы создать локальную ветку, соответствующую удалённой.

Переименовать локальную ветку

git branch -m oldname newname

Вернуться к любому коммиту

Можно использовать git reset , как показано ранее. Это будет означать, что вы хотите навсегда вернуться к тому состоянию, в котором вы были, а не просто посмотреть на него (для этого надо сделать checkout). Идентификатор коммита должен быть такой, какой прописан в выводе команды git log .

git reset --hard идентификатор_коммита

Ещё раз повторим: команда отменит все текущие изменения, так что убедитесь, что вам это действительно нужно. Или используйте --soft вместо --hard.

Удалить подмодуль (submodule)

Создание подмодулей используется довольно редко, но иногда они всё-таки встречаются. Вот, что вам нужно:

git submodule deinit submodulename
git rm submodulename
git rm --cached submodulename
rm -rf .git/modules/submodulename

Перезаписать локальные файлы во время git pull

Вам снова поможет git reset :

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

Как добавить пустую директорию в репозиторий?

Никак! Такая возможность просто не поддерживается, т.к. считается, что вам это не нужно. Но есть один трюк. Можно создать файл .gitignore в нужной директории со следующим содержимым:

Экспортирование исходников аналогично «svn export»

Используйте git archive , например, так:

git archive --format zip --output /путь/к/файлу/файл.zip master

Читайте также: