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

3860

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

Я сделал:

git reset --hard HEAD

Но когда я бегу git status,

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
      modified:   java/com/mycompany/TestContacts.java
      modified:   java/com/mycompany/TestParser.java

Подскажите, пожалуйста, почему у меня эти «модифицированные»? Я не трогал эти файлы? Если я это сделаю, я хочу удалить их.

hap497
источник
8
По выводу git statusваша вторая команда git reset --hard HEADне удалась. Вы не вставили его вывод, хотя. → Неполный вопрос.
Роберт Симер
2
Здесь вы смешиваете две проблемы: 1) как сбросить локальную ветвь до точки, где находится пульт, и 2) как очистить вашу промежуточную область (и, возможно, рабочий каталог), так что git statusговорится nothing to commit, working directory clean. - Пожалуйста уточни!
Роберт Симер

Ответы:

6702

Настройка ветки в точном соответствии с удаленной веткой может быть выполнена в два шага:

git fetch origin
git reset --hard origin/master

Если вы хотите сохранить текущее состояние вашей ветви перед этим (на всякий случай), вы можете сделать:

git commit -a -m "Saving my work, just in case"
git branch my-saved-work

Теперь ваша работа сохраняется в ветке "my-сохраненная работа" на тот случай, если вы решите, что хотите вернуть ее (или хотите посмотреть на нее позже или сравнить ее с обновленной веткой).

Обратите внимание, что в первом примере предполагается, что имя удаленного репо - «происхождение» и что ветвь с именем «master» в удаленном репо совпадает с извлеченной в данный момент веткой в ​​вашем локальном репо.

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

Дэн Молдинг
источник
4
Спасибо за ваш ответ. Вы сказали: «Обратите внимание, что в первом примере предполагается, что имя удаленного репо -« origin », и что ветка с именем« master »в удаленном репо совпадает с веткой в ​​вашем локальном репо». Как я могу дважды проверить имя моего удаленного репо и имя моей ветви, чтобы быть уверенным, прежде чем я выполню 'git reset --hard'? Еще раз спасибо.
hap497
21
Если вы не указали имя пульта в явном виде, то его имя, скорее всего, просто «происхождение» (по умолчанию). Вы можете использовать «git remote», чтобы получить список всех удаленных имен. Затем вы можете использовать «git remote <name>», чтобы увидеть, какие ветви push / pull друг с другом (например, если ваша «master» ветка была клонирована из «master» в удаленном устройстве с именем «origin», то вы получите строку что говорит "мастер сливается с удаленным мастером").
Дэн Молдинг
6
«Не рекомендуется вставлять в не обнаженное хранилище (и не в
текущую
27
Сразу после получения, я думаю, что вы также можете сделать git reset FETCH_HEAD --hardто же самое.
Жан
6
Он не удалял файлы, которые я добавил.
Трисмегистос
417

Мне нужно было сделать (решение в принятом ответе):

git fetch origin
git reset --hard origin/master

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

git clean -f

удалить локальные файлы

Чтобы увидеть, какие файлы будут удалены (без их фактического удаления):

git clean -n -f
Akavall
источник
89
также, git clean -d -fесли есть неотслеживаемые каталоги.
Гар
54
такжеgit clean -fdx
Свопнил Котвал
14
Если вам нужна точная копия удаленной ветки, вы должны использовать git clean -ffdx. Обратите внимание, что есть два f.
Трисмегистос
6
Это git clean -fбыла необходимая вещь, которая мне была нужна. Спасибо!
августа
17
будьте осторожны, используя команду clean. он может удалять игнорируемые файлы из других веток.
mikoop
307

Сначала вернемся к ранее выбранной HEADсоответствующей ветви восходящего направления:

git reset --hard @{u}

Преимущество указания @{u}или его подробной формы @{upstream}заключается в том, что имя удаленного репо и филиала не нужно указывать явно.

Затем, при необходимости, удалите неотслеживаемые файлы, при необходимости также с помощью -x:

git clean -df

Наконец, по мере необходимости, получите последние изменения:

git pull
Акаменус
источник
54
Это кажется лучшим ответом, чем принятый, потому что он динамически сбрасывается в текущую ветвь восходящего потока, а не всегда в статический, такой какorigin/master
Jon z
@Jonz пятно, @{upstream}очень удобно и может использоваться в псевдонимах:alias resetthisbranch="git reset --hard @{upstream}"
Сиддхартха
1
@GangadharJannu git reset --hardтребует коммита, иначе он не будет знать, на что вас сбросить. @{u}указывает на конкретный коммит - голову отслеживаемой ветви, с момента, когда вы в последний раз делали a git fetch.
Кристоффер Баккейорд
1
@KristofferBakkejord Спасибо за объяснение, но даже без хеша коммита мы можем сделать, git reset --hardхотя он не будет сброшен в удаленную ветвь
Gangadhar JANNU
3
Для тех, кто чуть не открыл новый вопрос здесь, если вы используете Git из Powershell, используйте quotes ( git reset --hard "@{u}"). Мне понадобилось время, чтобы понять это.
MPStoering
112

git reset --hard HEADфактически сбрасывается только до последнего совершенного состояния. В этом случае HEAD означает HEAD вашей ветки.

Если у вас есть несколько коммитов, это не сработает ..

То, что вы, вероятно, хотите сделать, - это сбросить на исходную точку или как называется ваш удаленный репозиторий. Я бы, наверное, просто сделал что-то вроде

git reset --hard origin/HEAD

Будьте осторожны, хотя. Жесткий сброс не может быть легко отменен. Лучше сделать, как предлагает Дэн, и перед сбросом отправьте копию своих изменений.

Микаэль Олсон
источник
2
В моем ответе было неверное предположение, которое Дэн поймал ранее. Я отредактировал это, так как я не хочу никого вводить в заблуждение. Что касается материала origin / master или origin / HEAD, я ожидаю, что это зависит от того, действительно ли вы сначала делаете выборку. Если вы только что клонировали источник, и у него не было других веток, что я нахожу довольно распространенным, тогда он должен сбросить его нормально. Но, конечно, Дэн прав.
Микаэль Олсон
73

Все вышеперечисленные предложения верны, но часто, чтобы действительно сбросить ваш проект, вам также нужно удалить даже файлы, которые есть в вашем .gitignore.

Чтобы получить моральный эквивалент удаления каталога проекта и повторного клонирования с удаленного компьютера, выполните следующие действия .

git fetch
git reset --hard
git clean -x -d -f

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

Кристофер Смит
источник
12
Предупреждение: «git clean -x -d -f» необратим, и вы можете потерять файлы и данные в .gitignore
Akarsh Satija
Немного короче: git clean -xdfэто равно git clean -x -d -f.
Кирилл
мерзавец чистый -ffxd , чтобы удалить все не в репо
Трисмегиста
44

Используйте команды ниже. Эти команды также удаляют все неотслеживаемые файлы из локального git

git fetch origin
git reset --hard origin/master
git clean -d -f
Джамшир
источник
6
Это более полный ответ, потому что без этого git clean -d -fу нас все еще были некоторые вещи старой ветки в локальном каталоге. Спасибо чувак.
Флавио
3
Это то, что на самом деле делает его таким же, как пульт. Чистота важна.
Дэвид С.
1
мерзавец чистый -ffxd к поистине удалить все
Трисмегиста
1
Это именно то, что мне было нужно. Спасибо
AllJs
38

Вопрос смешивает два вопроса здесь:

  1. как сбросить локальную ветку до точки где удаленный
  2. как очистить вашу промежуточную область (и, возможно, рабочий каталог), так что git statusговоритnothing to commit, working directory clean.

Единый ответ:

  1. git fetch --prune (необязательно) Обновляет локальный снимок удаленного репо. Дальнейшие команды только локальные.
    git reset --hard @{upstream}Помещает указатель локальной ветки туда, где находится снимок удаленного устройства, а также устанавливает индекс и рабочий каталог для файлов этого коммита.
  2. git clean -d --force Удаляет неотслеживаемые файлы и каталоги, которые мешают git сказать «рабочий каталог чист».
Роберт Симер
источник
1
@{upstream}Синтаксис требует вверх по течению , чтобы быть множество , которое происходит по умолчанию , если вам git checkout <branchname>. - В противном случае замените его на origin/<branchname>.
Роберт Симер
Добавьте, -xчтобы git cleanудалить все, что не входит в коммит (то есть даже файлы, игнорируемые механизмом .gitignore).
Роберт Симер
22

С этим я регулярно сталкиваюсь, и я обобщил приведенный выше скрипт Вольфганга для работы с любой веткой.

Я также добавил приглашение «Вы уверены» и вывод обратной связи?

#!/bin/bash
# reset the current repository
# WF 2012-10-15
# AT 2012-11-09
# see http://stackoverflow.com/questions/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
branchname=`git rev-parse --symbolic-full-name --abbrev-ref HEAD`
read -p "Reset branch $branchname to origin (y/n)? "
[ "$REPLY" != "y" ] || 
echo "about to auto-commit any changes"
git commit -a -m "auto commit at $timestamp"
if [ $? -eq 0 ]
then
  echo "Creating backup auto-save branch: auto-save-$branchname-at-$timestamp"
  git branch "auto-save-$branchname-at-$timestamp" 
fi
echo "now resetting to origin/$branchname"
git fetch origin
git reset --hard origin/$branchname
Эндрю Таллох
источник
3
Вы можете использовать «git remote», чтобы получить имя удаленного. В некоторых случаях это не будет «происхождение»
Юрик
17

При условии, что удаленный репозиторий есть origin, и что вас интересует branch_name:

git fetch origin
git reset --hard origin/<branch_name>

Кроме того, вы идете для сброса текущей ветви originв HEAD.

git fetch origin
git reset --hard origin/HEAD

Как это работает:

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

Затем git resetсбрасывает <branch_name>ветку к тому, что вы только что получили. --hardОпция изменяет все файлы в вашем рабочем дереве , чтобы соответствовать файлам origin/branch_name.

eigenharsha
источник
14

Я сделал:

git branch -D master
git checkout master

полностью сбросить ветку


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

user2846569
источник
5
Вы должны прочитать вопрос еще раз, ничего не влияет на удаленный доступ, кроме настройки на то же самое, что и удаленный, так что вы ничего не должны делать с удаленным, и это помогло в моем случае, а не выше.
user2846569
Если вы хотите установить его так же, как удаленный, вы должны по крайней мере сделать выборку в какой-то момент, вы не согласны?
Тим
2
по крайней мере, вы должны попробовать это или прочитать документы: kernel.org/pub/software/scm/git/docs/git-checkout.html
user2846569
Кстати, у меня был испорченный файл .pck в ветке, а остальные опции не работали, спасибо !!
LuckyBrain
14

Вот скрипт, который автоматизирует то, что предлагает самый популярный ответ ... См. Https://stackoverflow.com/a/13308579/1497139 для улучшенной версии, которая поддерживает ветви

#!/bin/bash
# reset the current repository
# WF 2012-10-15
# see /programming/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
git commit -a -m "auto commit at $timestamp"
if [ $? -eq 0 ]
then
  git branch "auto-save-at-$timestamp" 
fi
git fetch origin
git reset --hard origin/master
Вольфганг Фаль
источник
10

Если у вас была проблема со мной, что вы уже совершили некоторые изменения, но теперь, по любой причине, вы хотите от нее избавиться, самый быстрый способ - использовать git resetвот так:

git reset --hard HEAD~2

У меня было 2 не нужных коммита, отсюда и номер 2. Вы можете изменить его на свое количество коммитов для сброса.

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

git reset --hard HEAD~5

Обратите внимание, что вы потеряете внесенные изменения, поэтому будьте осторожны!

Karol
источник
7

Предыдущие ответы предполагают, что ветвь, которая будет сброшена, является текущей веткой (проверено). В комментариях OP hap497 пояснил, что ветка действительно проверена, но это не требуется явно в исходном вопросе. Поскольку существует хотя бы один «повторяющийся» вопрос, полностью сбросьте ветвь в состояние хранилища , что не предполагает, что ветвь извлечена, вот альтернатива:

Если ветвь "mybranch" в настоящее время не извлечена, чтобы сбросить ее до заголовка удаленной ветки "myremote / mybranch", вы можете использовать команду низкого уровня :

git update-ref refs/heads/mybranch myremote/mybranch

Этот метод оставляет проверенную ветку такой, какая она есть, и рабочее дерево нетронутым. Он просто перемещает голову mybranch на другой коммит, независимо от того, что указано в качестве второго аргумента. Это особенно полезно, если необходимо обновить несколько веток до новых удаленных голов.

При этом соблюдайте осторожность и используйте gitkили аналогичный инструмент для двойной проверки источника и назначения. Если вы случайно сделаете это в текущей ветке (и git не помешает вам), вы можете запутаться, потому что новое содержимое ветки не соответствует рабочему дереву, которое не изменилось (чтобы исправить, обновите ветку снова, туда, где это было раньше).

Райнер Блум
источник
7

Это то, что я часто использую:

git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force;

Обратите внимание , что это хорошая практика , чтобы не вносить изменения в свой местный мастер / развивать отрасль, но вместо того, чтобы фотографии на другую ветку для каких - либо изменений, с именем ветви предварённого по типу изменения, например feat/, chore/, fix/и т.д. Таким образом , вам нужно только тянуть изменения, а не выдвигать изменения от мастера. То же самое для других отраслей, которым способствуют другие. Таким образом, вышеприведенное следует использовать только в том случае, если вы зафиксировали изменения в ветке, в которую зафиксировали другие, и вам необходимо выполнить сброс. В противном случае в будущем избегайте нажатия на ветку, к которой другие подталкивают, вместо этого извлекайте и переходите к указанной ветке через извлеченную ветку.

Если вы хотите сбросить свою локальную ветвь до последнего коммита в ветке upstream, у меня пока работает:

Проверьте свои пульты, убедитесь, что ваш апстрим и источник - это то, что вы ожидаете, если не так, как ожидалось, тогда используйте git remote add upstream <insert URL>, например, оригинальное репозиторий GitHub, с которого вы ответили, и / или git remote add origin <insert URL of the forked GitHub repo>.

git remote --verbose

git checkout develop;
git commit -m "Saving work.";
git branch saved-work;
git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force

В GitHub вы также можете извлекать ветку с тем же именем, что и у локальной, чтобы сохранить там работу, хотя в этом нет необходимости, если в origin development есть те же изменения, что и в локальной ветке сохраненной работы. Я использую ветвь разработки в качестве примера, но это может быть любое существующее имя ветки.

git add .
git commit -m "Reset to upstream/develop"
git push --force origin develop

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

git merge -s recursive -X theirs develop

Во время использования

git merge -s recursive -X ours develop

чтобы сохранить конфликтующие изменения branch_name. В противном случае используйте mergetool с git mergetool.

Со всеми изменениями вместе:

git commit -m "Saving work.";
git branch saved-work;
git checkout develop;
git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force;
git add .;
git commit -m "Reset to upstream/develop";
git push --force origin develop;
git checkout branch_name;
git merge develop;

Обратите внимание, что вместо upstream / development вы могли бы использовать хеш коммита, другое имя ветки и т. Д. Используйте инструмент CLI, такой как Oh My Zsh, чтобы проверить, что ваша ветвь имеет зеленый цвет, указывая, что нет ничего для фиксации, а рабочий каталог чистый ( что подтверждается или также проверяется git status). Обратите внимание , что это может на самом деле добавить фиксации по сравнению с выше по течению развиваться , если есть что - то автоматически добавляет фиксацию, например , UML диаграммы, лицензионные заголовки и т.д., так что в этом случае, вы могли бы тянуть изменения на , origin developчтобы upstream develop, в случае необходимости.

Джеймс Рэй
источник
6

Ответ

git clean -d -f

был недооценен ( -d для удаления каталогов). Спасибо!

АНАЭЛЬ
источник
И для полной, 100% чистой папки репо без лишних файлов, запустите git clean -xdf. Это удалит все файлы, которые git не знает, и сделает вашу папку точно совпадающей с тем, что находится в списке объектов git. Обратите внимание, что вы можете добавить -n(например git clean -nxdf) выполнить «что-если», и он скажет вам, что он удалит, фактически ничего не делая. ( git clean )
qJake
5

Если вы хотите вернуться в HEADсостояние как для рабочего каталога, так и для индекса, то вам лучше git reset --hard HEADвместо этого HEAD^. (Это может быть опечатка, точно так же, как для одиночного или двойного тире --hard.)

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

Эмиль Сит
источник
4

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

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

xkcd: Git

Мартин
источник
1

Единственное решение, которое работает во всех случаях, которые я видел, это удалить и откинуть. Может быть, есть другой путь, но, очевидно, этот путь не оставляет шансов на то, что старое государство останется там, поэтому я предпочитаю это. Bash one-liner вы можете установить как макрос, если вы часто путаетесь в git:

REPO_PATH=$(pwd) && GIT_URL=$(git config --get remote.origin.url) && cd .. && rm -rf $REPO_PATH && git clone --recursive $GIT_URL $REPO_PATH && cd $REPO_PATH

* предполагает, что ваши .git файлы не повреждены

Судо
источник
4
Вы также можете просто переустановить операционную систему, если хотите быть уверенным!
Себастьян Шолле
1

Вы забыли создать функциональную ветвь и по ошибке совершили прямой переход на мастер?

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

git checkout -b feature-branch
git branch -f master origin/master
Grastveit
источник
1

Только 3 команды сделают это

git fetch origin
git reset --hard origin/HEAD
git clean -f
Deep Nirmal
источник
-3

Если вы не против сохранить свои локальные изменения, но все же хотите обновить свой репозиторий, чтобы он соответствовал origin / HEAD, вы можете просто сохранить свои локальные изменения и затем нажать:

git stash
git pull
Мика Уолтер
источник