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

<p>как принудительно перезаписать локальные файлы в <code>git pull</code>?</p><p>сценарий следующий:</p><ul> <li>член команды модифицирует шаблоны для сайта, над которым мы работаем</li> <li>они добавляют некоторые изображения в каталог изображений (но забывают добавить их под контролем исходного кода)</li> <li>они отправляют изображения по почте, позже, мне</li> <li>я добавляю изображения под контроль исходного кода и помещаю их в github вместе с другими изменениями.</li> <li>они не могут получать обновления из github, потому что git не хочет перезаписывать свои файлы.</li> </ul><p>это ошибка, которую я получаю:</p><blockquote> <p>ошибка: неотслеживаемый файл рабочего дерева 'public/images/icon.gif' будет перезаписан слиянием</p> </blockquote><p>как заставить git перезаписать их? этот человек дизайнер. обычно я разрешаю все конфликты вручную, поэтому на сервере установлена самая последняя версия, которую им просто необходимо обновить на своем компьютере.</p>

<h2>важно: если у вас есть какие-либо локальные изменения, они будут потеряны. с параметром <code>--hard</code> или без него все локальные коммиты, которые не были переданы, будут потеряны.<sup>[*]</sup></h2><p>если у вас есть файлы, которые<em> не </em>отслеживаются git (например, загруженный пользовательский контент), эти файлы не будут затронуты.</p><hr><p>я думаю, что это правильный путь:</p><pre><code>git fetch --all </code></pre><p>тогда у вас есть два варианта:</p><pre><code>git reset --hard origin/master </code></pre><p>или если вы находитесь в другой ветке:</p><pre><code>git reset --hard origin/<branch\_name> </code></pre><h3>объяснение:</h3><p><code>git fetch</code> загружает последние с удаленного, не пытаясь объединить или перебазировать что-либо.</p><p>затем <code>git reset</code> сбрасывает основную ветвь к тому, что вы только что получили. параметр <code>--hard</code> изменяет все файлы в рабочем дереве в соответствии с файлами в <code>origin/master</code></p><hr><h3>поддерживать текущие локальные коммиты</h3><p><sup>[*]</sup>: стоит отметить, что можно поддерживать текущие локальные коммиты, создав ветку из <code>master</code> перед сбросом:</p><pre><code>git checkout master git branch new-branch-to-save-current-commits git fetch --all git reset --hard origin/master </code></pre><p>после этого все старые коммиты будут храниться в <code>new-branch-to-save-current-commits</code>. </p><h3>незавершенные изменения</h3><p>однако незафиксированные изменения (даже поэтапные) будут потеряны. убедитесь, что вы спрятали и передали все, что вам нужно. для этого вы можете запустить следующее:</p><pre><code>git stash </code></pre><p>а затем повторно применить эти незафиксированные изменения:</p><pre><code>git stash pop </code></pre>

<p>попробуй это:</p><pre><code>git reset --hard head git pull </code></pre><p>это должно делать то, что вы хотите.</p>

<p><strong> внимание: <code>git clean</code> удаляет все ваши неотслеживаемые файлы/каталоги и не может быть отменен. </strong></p><hr><p>иногда просто <code>clean -f</code> не помогает. если у вас нет отслеживаемых каталогов, опция -d также необходима:</p><pre><code># warning: this can't be undone! git reset --hard head git clean -f -d git pull </code></pre><p><strong> внимание: <code>git clean</code> удаляет все ваши неотслеживаемые файлы/каталоги и не может быть отменен. </strong></p><p>попробуйте сначала использовать флаг <code>-n</code> (<code>--dry-run</code>). это покажет вам, что будет удалено, фактически не удаляя ничего:</p><pre><code>git clean -n -f -d </code></pre><p>пример вывода:</p><pre><code>would remove untracked-file-1.txt would remove untracked-file-2.txt would remove untracked/folder ... </code></pre>

<p>как и ежик, я думаю, что ответы ужасны. но хотя ответ ежика мог бы быть лучше, я не думаю, что он такой элегантный, как мог бы быть. я нашел способ сделать это с помощью «выборки» и «слияния» с определенной стратегией. что должно сделать так, чтобы ваши локальные изменения сохранялись до тех пор, пока они не являются одним из файлов, которые вы пытаетесь перезаписать. </p><h3>сначала сделайте коммит ваших изменений</h3><pre><code> git add * git commit -a -m "local file server commit message" </code></pre><h3>затем извлеките изменения и перепишите, если есть конфликт</h3><pre><code> git fetch origin master git merge -s recursive -x theirs origin/master </code></pre><p>«-x» - это имя опции, а «их» - значение для этой опции. вы решаете использовать «свои» изменения, а не «свои», если есть конфликт.</p>

<p>вместо того, чтобы делать:</p><pre><code>git fetch --all git reset --hard origin/master </code></pre><p>я бы посоветовал сделать следующее:</p><pre><code>git fetch origin master git reset --hard origin/master </code></pre><p>не нужно извлекать все пульты и ветки, если вы собираетесь сбросить в исходную/основную ветку, верно?</p>

<p>похоже, лучше всего сначала сделать:</p><pre><code>git clean </code></pre><p>чтобы удалить все неотслеживаемые файлы, а затем продолжите с обычного <code>git pull</code>...</p>

<p> <a href="http://blog.icefusion.co.uk/git-stash-can-delete-ignored-files-git-stash-u/"><strong>предупреждение, это навсегда удалит ваши файлы, если у вас есть какие-либо записи каталога/* в вашем файле gitignore.</strong></a> </p><p>некоторые ответы кажутся ужасными. ужасно в смысле того, что случилось с @lauri, следуя предложению давида авсаджанишвили.</p><p>скорее (git> v1.7.6):</p><pre><code>git stash --include-untracked git pull </code></pre><p>позже вы можете очистить тайник истории.</p><p>вручную, один за другим:</p><pre><code>$ 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 </code></pre><p>конечно, если вы хотите вернуться к тому, что вы спрятали:</p><pre><code>$ git stash list ... $ git stash apply stash@{5} </code></pre>

<p>эта команда может оказаться полезной для удаления локальных изменений:</p><pre><code>git checkout <your-branch> -f </code></pre><p>а затем выполните очистку (удаляет неотслеживаемые файлы из рабочего дерева):</p><pre><code>git clean -f </code></pre><p>если вы хотите удалить неотслеживаемые каталоги в дополнение к неотслеживаемым файлам:</p><pre><code>git clean -fd </code></pre>

<p>вместо слияния с <code>git pull</code>, попробуйте это: </p><p><code>git fetch --all</code></p><p>с последующим:</p><p><code>git reset --hard origin/master</code>.</p>

<p>единственное, что сработало для меня, было:</p><pre><code>git reset --hard head~5 </code></pre><p>это вернет вам пять коммитов, а затем</p><pre><code>git pull </code></pre><p>я нашел это, посмотрев вверх <a href="https://stackoverflow.com/questions/2389361/git-undo-a-merge">как отменить слияние git</a> .</p>

<p>проблема со всеми этими решениями заключается в том, что все они либо слишком сложны, либо, что еще важнее, они удаляют все неотслеживаемые файлы с веб-сервера, что нам не нужно, поскольку всегда есть необходимые файлы конфигурации, которые находятся на сервер а не в репозитории git.</p><p>вот самое чистое решение, которое мы используем:</p><pre class="lang-bash prettyprint-override"><code># 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 </code></pre><ul> <li><p>первая команда выбирает новейшие данные.</p></li> <li><p>вторая команда проверяет, есть ли какие-либо файлы, которые добавляются в хранилище, и удаляет те неотслеживаемые файлы из локального хранилища, которые могут вызвать конфликты.</p></li> <li><p>третья команда проверяет все файлы, которые были локально изменены.</p></li> <li><p>наконец, мы делаем попытку обновления до последней версии, но на этот раз без каких-либо конфликтов, так как неотслеживаемые файлы, которые находятся в репо, больше не существуют, и все локально измененные файлы уже такие же, как в репозитории.</p></li> </ul>

<p>у меня такая же проблема. никто не дал мне это решение, но оно сработало для меня.</p><p>я решил это:</p><ol> <li>удалить все файлы. оставьте только каталог <code>.git</code>.</li> <li><code>git reset --hard head</code></li> <li><code>git pull</code></li> <li><code>git push</code></li> </ol><p>теперь это работает.</p>

<p>прежде всего, попробуйте стандартный способ:</p><pre><code>git reset head --hard # to remove all not committed changes! git clean -fd # to remove all untracked (non-git) files and folders! </code></pre><p><sup><strong> предупреждение </strong>: приведенные выше команды могут привести к потере данных/файлов, только если они не зафиксированы! если вы не уверены, сначала сделайте резервную копию всей вашей папки репозитория.</sup></p><p>тогда потяните это снова.</p><p>если вышеперечисленное не поможет и вам не нужны ваши неотслеживаемые файлы/каталоги (на всякий случай сделайте резервную копию сначала), попробуйте выполнить следующие простые шаги:</p><pre><code>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 </code></pre><p>это удалит все файлы git (за исключением <code>.git/</code> dir, где у вас есть все коммиты) и извлечет его снова.</p><hr><p>почему <code>git reset head --hard</code> может не работать в некоторых случаях?</p><ol> <li><p>пользовательские правила в <code>.gitattributes file</code></p> <p>наличие правила <code>eol=lf</code> в .gitattributes может привести к тому, что git изменит некоторые изменения файла, преобразовав окончания строк crlf в lf в некоторых текстовых файлах.</p> <p>если это так, вы должны зафиксировать эти изменения crlf/lf (просмотрев их в <code>git status</code>) или попробуйте: <code>git config core.autcrlf false</code>, чтобы временно их игнорировать.</p></li> <li><p>несовместимость файловой системы</p> <p>когда вы используете файловую систему, которая не поддерживает атрибуты разрешений . например, у вас есть два репозитория, один для linux/mac (<code>ext3</code>/<code>hfs+</code>) и другой для файловой системы на основе fat32/ntfs.</p> <p>как вы заметили, существует два разных типа файловых систем, поэтому та, которая не поддерживает разрешения unix, в основном не может сбросить разрешения для файлов в системе, которая не поддерживает такого рода разрешения, поэтому независимо от того, как <code>--hard</code> вы пытаетесь, git всегда обнаруживает некоторые "изменения".</p></li> </ol>

<h3>бонус:</h3><p>говоря о pull/fetch/merge в предыдущих ответах, я хотел бы поделиться интересным и продуктивным приемом:</p><h1><strong><code>git pull --rebase</code></strong></h1><p>эта команда является самой полезной в моей жизни в git, которая сэкономила много времени.</p><p>перед отправкой вашего нового коммита на сервер, попробуйте эту команду, и она автоматически синхронизирует последние изменения на сервере (с выборкой + слиянием) и поместит ваш коммит наверху в журнале git. нет необходимости беспокоиться о ручном извлечении/слиянии.</p><p>найти подробности в <em> <a href="http://gitolite.com/git-pull--rebase">что делает "git pull --rebase"?</a> </em>.</p>

<p>у меня была похожая проблема. я должен был сделать это:</p><pre><code>git reset --hard head git clean -f git pull </code></pre>

<p>я суммировал другие ответы. вы можете выполнить <code>git pull</code> без ошибок:</p><pre><code>git fetch --all git reset --hard origin/master git reset --hard head git clean -f -d git pull </code></pre><p><strong> предупреждение </strong>: этот скрипт очень мощный, поэтому вы можете потерять свои изменения.</p>

<p>основываясь на моем собственном подобном опыте, решение, предложенное strahinja kustudic выше, является безусловно лучшим. как уже отмечали другие, просто сделать hard reset удалит<strong> все </strong>неотслеживаемые файлы, которые могут включать в себя множество вещей, которые вы не хотите удалять, такие как файлы конфигурации. более безопасным является удаление только тех файлов, которые будут добавлены, и в этом отношении вы, вероятно, также захотите извлечь любые локально-модифицированные файлы, которые будут обновлены.</p><p>имея это в виду, я обновил сценарий кустудича, чтобы сделать именно это. я также исправил опечатку (отсутствует в оригинале).</p><pre class="lang-bash prettyprint-override"><code>#/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 </code></pre>

<p>я полагаю, что есть две возможные причины конфликта, которые должны быть устранены отдельно, и, насколько я могу судить, ни один из приведенных выше ответов не касается обоих:</p><ul> <li><p>локальные файлы, которые не были отслежены, необходимо удалить вручную (безопаснее) или, как предлагается в других ответах, с помощью <code>git clean -f -d</code></p></li> <li><p>локальные коммиты, которые не находятся в удаленной ветке, также должны быть удалены. imo самый простой способ добиться этого с помощью: <code>git reset --hard origin/master</code> (замените 'master' на ту ветку, над которой вы работаете, и сначала запустите <code>git fetch origin</code>)</p></li> </ul>

<p>более простым способом было бы:</p><pre><code>git checkout --theirs /path/to/file.extension git pull origin master </code></pre><p>это заменит ваш локальный файл с файлом на git</p>

<p>кажется, что большинство ответов здесь сосредоточены на ветви <code>master</code>; однако бывают случаи, когда я работаю над одной и той же веткой функций в двух разных местах, и я хочу, чтобы ребаз в одном отражался в другом, не перепрыгивая через обручи.</p><p>основываясь на комбинации <a href="https://stackoverflow.com/a/8888015/1103543">ответа рнк</a> и <a href="https://stackoverflow.com/a/19961461/1103543">ответа торека на похожий вопрос</a> , я придумала это, которое прекрасно работает:</p><pre><code>git fetch git reset --hard @{u} </code></pre><p>запустите это из ветки, и она будет только сбрасывать вашу локальную ветку на версию для апстрима.</p><p>это также можно поместить в псевдоним git (<code>git forcepull</code>):</p><p><code>git config alias.forcepull "!git fetch ; git reset --hard @{u}"</code></p><p>или в вашем файле <code>.gitconfig</code>:</p><pre><code>[alias] forcepull = "!git fetch ; git reset --hard @{u}" </code></pre><p>наслаждайтесь!</p>

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

<p>я просто решил это сам:</p><pre class="lang-bash prettyprint-override"><code>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 </code></pre><p>где последняя команда дает список ваших локальных изменений. продолжайте изменять ветку «tmp» до тех пор, пока она не станет приемлемой, а затем вернитесь к master с помощью: </p><pre><code>git checkout master && git merge tmp </code></pre><p>в следующий раз вы, вероятно, сможете справиться с этим более чистым способом, посмотрев «ветку git stash», хотя stash, вероятно, вызовет у вас проблемы при первых нескольких попытках, поэтому проведите первый эксперимент на некритическом проекте ...</p>

<p>у меня странная ситуация, когда ни <code>git clean</code>, ни <code>git reset</code> не работают. я должен удалить конфликтующий файл из <code>git index</code>, используя следующий скрипт для каждого неотслеживаемого файла:</p><pre><code>git rm [file] </code></pre><p>тогда я могу тянуть просто отлично.</p>

<p>я знаю гораздо более простой и менее болезненный метод:</p><pre><code>$ git branch -m [branch_to_force_pull] tmp $ git fetch $ git checkout [branch_to_force_pull] $ git branch -d tmp </code></pre><p>это оно!</p>

<p>эти четыре команды работают для меня.</p><pre><code>git reset --hard head git checkout origin/master git branch -d master git checkout -b master </code></pre><p>чтобы проверить/вытащить после выполнения этих команд</p><pre><code>git pull origin master </code></pre><p>я много пробовал, но наконец-то добился успеха с этими командами.</p>

<p>просто делать</p><pre><code>git fetch origin branchname git checkout -f origin/branchname // this will overwrite only new included files git checkout branchname git merge origin/branchname </code></pre><p>таким образом, вы избегаете всех нежелательных побочных эффектов, таких как удаление файлов или каталогов, которые вы хотели сохранить, и т.д.</p>

<p>несмотря на исходный вопрос, ответы на часто задаваемые вопросы могут вызвать проблемы у людей, которые имеют аналогичную проблему, но не хотят терять свои локальные файлы. например, см. комментарии al-punk и crizcraig. </p><p>следующая версия фиксирует ваши локальные изменения во временной ветви (<code>tmp</code>), проверяет исходную ветку (я предполагаю, что <code>master</code>) и объединяет обновления. вы можете сделать это с <code>stash</code>, но я обнаружил, что обычно проще использовать подход ветвления/слияния.</p><pre><code>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 </code></pre><p>где мы предполагаем, что<strong> другой репозиторий </strong>это <code>origin master</code>.</p>

<p>сбросьте индекс и заголовок на <code>origin/master</code>, но не сбрасывайте рабочее дерево:</p><pre><code>git reset origin/master </code></pre>

<p>требования:</p><ol> <li>отслеживайте локальные изменения, чтобы никто их здесь не потерял.</li> <li>сделайте так, чтобы локальный репозиторий соответствовал удаленному репозиторию origin.</li> </ol><p>решение:</p><ol> <li><strong> копить </strong>локальные изменения.</li> <li><p><strong> выбрать </strong>с<strong> очистить </strong>из<strong> файлов </strong>и<strong> каталоги </strong>игнорировать<strong> .gitignore </strong>и<strong> полный сброс </strong>к<strong> происхождение </strong>.</p> <pre><code>git stash --include-untracked git fetch --all git clean -fdx git reset --hard origin/master </code></pre></li> </ol>

<p>я прочитал все ответы, но я искал одну команду, чтобы сделать это. вот что я сделал. добавлен псевдоним git для .gitconfig</p><pre><code>[alias] fp = "!f(){ git fetch ${1} ${2} && git reset --hard ${1}/${2};};f" </code></pre><p>запустите вашу команду как </p><pre><code>git fp origin master </code></pre><p>эквивалентно</p><pre><code>git fetch origin master git reset --hard origin/master </code></pre>

<p>не используйте <code>git reset --hard</code>. это сотрет их изменения, которые могут быть совершенно нежелательными. вместо:</p><pre><code>git pull git reset origin/master git checkout <file1> <file2> ... </code></pre><p>конечно, вы можете использовать <code>git fetch</code> вместо <code>git pull</code>, поскольку он явно не собирается сливаться, но если вы обычно тянете, имеет смысл продолжать тянуть здесь.</p><p>итак, что здесь происходит, это то, что <code>git pull</code><strong> обновляет вашу исходную/основную ссылку </strong>; <code>git reset</code><strong> обновляет вашу локальную ссылку на ветвь </strong>on так, чтобы она совпадала с origin/master без обновления каких-либо файлов, поэтому ваше состояние извлечения остается неизменным; затем <code>git checkout</code><strong> возвращает файлы в состояние индекса вашей локальной ветви </strong>по мере необходимости. в тех случаях, когда один и тот же файл был добавлен в прямом эфире и на главном канале, индекс уже соответствует файлу после сброса, поэтому в общем случае вам вообще не нужно делать <code>git checkout</code>.</p><p>если вышестоящая ветвь также содержит коммиты, которые вы хотите применить автоматически, вы можете следовать тонкому изменению процесса:</p><pre><code>git pull git merge <commit before problem commit> git reset <problem commit> git checkout <file1> <file2> ... git pull </code></pre>

<p>это лучшая практика для отмены изменений:</p><ul> <li><code>git commit</code> зафиксируйте свои поэтапные изменения, чтобы они были сохранены в <strong> <a href="https://git-scm.com/docs/git-reflog">reflog</a> </strong> (см. ниже)</li> <li><code>git fetch</code> извлекать последние вышестоящие изменения</li> <li><code>git reset --hard origin/master</code> хард ресет в основную ветку origin</li> </ul><p> <a href="https://git-scm.com/docs/git-reflog">reflog</a> <em>записывает ветки и другие ссылки, обновляемые в локальном хранилище</em>. или проще говоря - <strong>reflog</strong> - это <strong>история ваших изменений</strong>.</p><p>так что это всегда отличная практика. коммиты добавляются в reflog, что гарантирует, что у вас всегда будет возможность получить удаленный код.</p>

<p>я использовал эту команду, чтобы избавиться от локальных файлов, не позволяющих мне выполнять извлечение/слияние. но будь осторожен! сначала запустите <code>git merge …</code>, чтобы увидеть, есть ли только те файлы, которые вы действительно хотите удалить.</p><pre><code>git merge origin/master 2>&1 >/dev/null | grep ^[[:space:]] | sed s/^[[:space:]]//g | xargs -l1 rm </code></pre><ul> <li><code>git merge</code> перечисляет среди прочего все эти файлы. им предшествует какой-то пробел.</li> <li><code>2>&1 >/dev/null</code> перенаправляет вывод ошибки на стандартную, так что она принимается <code>grep</code>.</li> <li><code>grep ^[[:space:]]</code> фильтрует только строки с именами файлов.</li> <li><code>sed s/^[[:space:]]//g</code> обрезает пробел с самого начала.</li> <li><code>xargs -l1 rm</code> вызывает <code>rm</code> для каждого из этих файлов, удаляя их.</li> </ul><p>обращайтесь с осторожностью: что бы ни выводил <code>git merge</code>, <code>rm</code> будет вызываться для<strong> каждой </strong>строки, начинающейся с пробела.</p>

<p>я пытался использовать ветку material2 на angular2-webpack-starter, и у меня было очень много времени. это был единственный способ загрузить и использовать эту ветку.</p><pre><code>git clone --depth 1 https://github.com/angularclass/angular2-webpack-starter.git cd angular2-webpack-starter/ git checkout -b material2 </code></pre><p>откройте папку проекта и удалите все не скрытые файлы и папки. оставь все скрытые.</p><pre><code>git add . git commit -m "pokemon go" git reset --hard git pull origin material2 </code></pre><p>(когда появится редактор, нажмите ": wq", а затем нажмите <kbd>enter</kbd>)</p><p>теперь вы готовы.</p>

<p>в windows выполните эту единственную команду:</p><pre><code>git fetch --all & git reset --hard origin/master </code></pre>

<p>вы можете игнорировать этот файл с файлом в базовой папке вашего проекта:</p><p>.gitignore</p><pre><code>public/images/* </code></pre><p>затем извлеките изменения и затем удалите эту строку из файла gitignore.</p>

<p><code>git fetch --all && git reset --hard origin/master && git pull</code></p>

<p>1: сброс до предыдущего коммита</p><pre><code>git reset --hard head </code></pre><p>2: удалить неотслеживаемые файлы</p><pre><code>git clean -f </code></pre><p>3: потяните коммиты</p><pre><code>git pull </code></pre><p>источники:</p><ul> <li> <a href="https://git-scm.com/docs/git-reset">https://git-scm.com/docs/git-reset</a> </li> <li> <a href="https://git-scm.com/docs/git-clean/">https://git-scm.com/docs/git-clean/</a> </li> </ul>

<p>если вы хотите выполнить общий сброс в ветке удаленного отслеживания, используйте:</p><pre><code>git fetch git reset --keep origin/$(git rev-parse --abbrev-ref head) если вы хотите сбросить локальные изменения:git fetch git reset --hard origin/$(git rev-parse --abbrev-ref head) </code></pre>