git переключает ветку, не отбрасывая локальные изменения

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

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

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

  • Резервное копирование измененного репо
  • git reset --hard
  • git checkout right-branch
  • Восстановить изменения
  • git commit -m "changes"

person megawac    schedule 27.02.2014    source источник


Ответы (6)


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

Возьмем классическую ошибку:

$ git checkout master
... pause for coffee, etc ...
... return, edit a bunch of stuff, then: oops, wanted to be on develop

Итак, теперь вы хотите, чтобы эти изменения, которые вы еще не зафиксировали в master, были в develop.

  1. Если у вас еще нет develop, метод тривиален:

    $ git checkout -b develop
    

    Это создаст новую ветку develop, начиная с того места, где вы сейчас находитесь. Теперь вы можете зафиксировать, и все новые вещи находятся на develop.

  2. У вас есть develop. Посмотрите, позволит ли Git вам переключиться без каких-либо действий:

    $ git checkout develop
    

    Это либо удастся, либо жаловаться. Если получится, отлично! Просто совершить. Если нет (error: Your local changes to the following files would be overwritten ...), у вас все еще есть много вариантов.

    Самый простой, вероятно, git stash (как сказали все другие ответчики, которые опередили меня, нажав post). Запустите git stash save или git stash push,1 или просто git stash, что является сокращением от save / push:

    $ git stash
    

    Это коммит вашего кода (да, он действительно делает некоторые коммиты) с использованием странного метода, не связанного с ветвями. Коммиты, которые он делает, не находятся «в» какой-либо ветке, но теперь безопасно хранятся в репозитории, поэтому теперь вы можете переключать ветки, а затем «применить» тайник:

    $ git checkout develop
    Switched to branch 'develop'
    $ git stash apply
    

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

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

Многие люди используют git stash pop, что является сокращением от git stash apply && git stash drop. Это нормально, но это означает, что если приложение приведет к беспорядку, и вы решите, что не хотите идти по этому пути, вы не сможете легко вернуть тайник. Вот почему я рекомендую отдельно apply, проверять результаты, drop только если/когда они удовлетворены. (Конечно, это вводит еще один момент, когда вы можете сделать еще один перерыв на кофе и забыть, что вы делали, вернуться и сделать неправильно вещь, так что это не идеальное лекарство.)


1 save в git stash save — это старый глагол для создания нового тайника. Git версии 2.13 представил новый глагол, чтобы сделать вещи более совместимыми с pop и добавить больше параметров в команду создания. В Git версии 2.16 старый глагол официально объявлен устаревшим (хотя он по-прежнему работает в Git 2.23, который является последним выпуском на момент редактирования этой статьи).

person torek    schedule 27.02.2014
comment
Что, если я хочу переключиться на другую ветку, не фиксируя текущую ветку (например, изменения не завершены), а затем переключиться обратно, чтобы продолжить? - person stt106; 08.11.2017
comment
@ stt106: вы все равно должны совершить фиксацию, но вы можете сделать это, как в этом и других ответах, через git stash, чтобы коммиты - для git stash вы получаете два коммита на запись тайника в необычном расположение — не находятся на никакой ветке. Однако, за исключением очень краткосрочных особых случаев, я обычно предпочитаю делать нормальную фиксацию. Вы можете git reset --soft или git reset --mixed позже или использовать git commit --amend, чтобы отодвинуть его в сторону, когда вы вернетесь к работе над этой веткой. (В современном Git вы также можете использовать git worktree add, что может быть даже лучшим решением.) - person torek; 08.11.2017
comment
Это либо преуспеет, либо пожалуется. Какие могут быть причины успеха или ошибки при оформлении заказа? - person nanocv; 13.03.2019
comment
@nanocv: см. stackoverflow.com/questions/22053757/ - person torek; 13.03.2019
comment
все мои локальные изменения теряются, когда я переключаюсь с помощью вышеуказанных шагов. Я нахожусь в ветке «a» и делаю свои изменения, и я хочу перейти в ветку «b» и отправить туда все свои изменения. когда я делаю git stash и перемещаюсь в другие ветки, он вытаскивает все файлы ветки ‹b›, и мои локальные изменения теряются - person Mukul Munjal; 17.05.2020
comment
@MukulMunjal: git stash означает сделать несколько коммитов, а затем удалить мои изменения, потому что они безопасно сохранены в коммитах тайника. Так что, конечно, они исчезнут после того, как вы их спрячете: смысл спрятать их, чтобы избавиться от них, а также сохранить их. Вы должны впоследствии удалить-спрятать их, используя git stash apply. В промежутке между этими двумя шагами вы можете переключать ветки сколько угодно. - person torek; 17.05.2020
comment
@torek - вы предполагаете, что git может содержать ошибку в абзаце: Таким образом, рекомендуется тщательно проверить результаты, прежде чем предположить, что тайник применен правильно, даже если сам Git не обнаружил никаких конфликтов слияния.? - person Shuzheng; 09.06.2020
comment
@Shuzheng: это не вопрос ошибок как таковых. Дело в том, что git merge не всеведущ: он следует простым правилам обработки текста. Обычно эти правила приводят к желаемому результату. Иногда это не так. Если вы запустите git stash pop, коммиты тайника будут потеряны, и их будет трудно вернуть, если вы хотите попробовать применить их к другому коммиту, который, например, может дать лучший результат. - person torek; 09.06.2020
comment
Остерегайтесь, неотслеживаемый файл (недавно добавленные файлы и незафиксированные) может быть потерян при первом git stash stackoverflow.com/questions/12147042/lost-git-stash-changes, поэтому создание новой ветки безопасно. - person Alsushi; 07.09.2020
comment
@Alsushi: в общем, git stash должен оставлять неотслеживаемые файлы в покое, а другие операции должны предупреждать вас, чтобы вы сначала убрали их с дороги. Однако включение файла в .gitignore, когда он находится в индексе (отслеживается), оставляет Git разрешение на уничтожение файла в некоторых случаях, в том числе и в этом. Однако файл будет сохранен в тайнике. - person torek; 07.09.2020
comment
Вам нужно зафиксировать и отправить локальные изменения в текущую ветку до git stash. Я потерял все свои локальные изменения до git stash, к счастью, история Pycharm помогла после воссоздания файлов. Лучше, как сказано, сделать нормальную фиксацию, а затем использовать git reset --soft или git reset --mixed позже - person Brian; 10.11.2020
comment
@Brian: git stash просто делает коммиты. Однако в git stash в нескольких версиях Git были добавлены ошибки, и в целом теперь я советую полностью избегать git stash, если это возможно. - person torek; 11.11.2020
comment
Я согласен с вами на 100% @torek - person Brian; 17.11.2020
comment
тлдр; не делай перерывов на кофе :D - person fbence; 17.04.2021
comment
Много текста и вводящих в заблуждение опасных команд. Мы на SO, чтобы сэкономить время, чтобы не читать 5-минутный текст с командами, которые потенциально могут уничтожить локальные изменения. Например. git checkout master хорош для истории, но если кто-то поторопится и запустит его, он просто потеряет все изменения. Проголосовали против - person rodi; 22.05.2021
comment
@rodi: не нравится мой ответ? Я верну все деньги, которые вы заплатили за него! - person torek; 23.05.2021
comment
torek Это конструктивное предложение, не принимайте его на свой счет :) Я надеюсь, что никто, включая людей, работающих в вашей команде, не потеряет деньги или время, потому что они потеряют свою работу. Ответ @Ray гораздо более функционален и соответствует принципам SO. - person rodi; 25.05.2021

Используйте git тайник

git stash

Он помещает изменения в стек. Если вы хотите вернуть их обратно, используйте

git stash apply

Вы даже можете вытащить отдельные предметы. Чтобы полностью сдуть тайник:

git stash clear
person Ray    schedule 27.02.2014
comment
Последняя команда, вероятно, должна быть git stash drop; git stash clear сотрет весь стек тайников, включая тайники, которые, возможно, не связаны с этим набором команд. - person Leland; 29.04.2019

  • git stash, чтобы сохранить незафиксированные изменения
  • git stash list чтобы просмотреть список сохраненных незафиксированных тайников
  • git stash apply stash@{x} где x может быть 0,1,2..количество тайников, которые вы сделали
person brokenfoot    schedule 27.02.2014

Ты можешь использовать :

  1. git stash чтобы сохранить свою работу
  2. git checkout <your-branch>
  3. git stash apply или git stash pop чтобы загрузить последнюю работу

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

документация по git -stash

person Andy Winarko    schedule 16.09.2020

Вы также можете :

  • Используйте git stash, чтобы отложить изменения или,

  • Создайте еще одну ветку и зафиксируйте там свои изменения, а затем объедините эту ветку в свой рабочий каталог.

person X3074861X    schedule 27.02.2014

Вы можете использовать --merge/-m git checkout вариант: git checkout -m <another-branch>

-м --слияние

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

Источник: https://git-scm.com/docs/git-checkout

person sergey.n    schedule 16.09.2020
comment
И попробуйте сначала просто git checkout thatbranch, который работает, если он полностью безопасен, если ни одно из ваших изменений вообще не касается файлов, обновленных при проверке. - person jthill; 22.01.2021
comment
@ sergey.n Думаю, твой ответ правильный. Сохранение не всегда работает, у него есть проблемы с подмодулями, стадированием, и если вы находитесь в ветке без коммитов, спрятать напрямую не получится. Однако вы всегда можете объединить изменения в новую ветку. - person Jeff Hykin; 02.05.2021