Git: Создать ветку из неустановленных / незафиксированных изменений на master

991

Контекст: я работаю над мастером, добавляя простую функцию. Через несколько минут я понимаю, что это было не так просто, и лучше было бы заняться новой веткой.

Это всегда случается со мной, и я понятия не имею, как переключиться на другую ветку и взять все эти незафиксированные изменения со мной, оставив главную ветвь чистой. Я предполагал git stash && git stash branch new_branchбы просто выполнить это, но вот что я получаю:

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ echo "hello!" > testing 

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git stash
Saved working directory and index state WIP on master: 4402b8c testing
HEAD is now at 4402b8c testing

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ git stash branch new_branch
Switched to a new branch 'new_branch'
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (db1b9a3391a82d86c9fdd26dab095ba9b820e35b)

~/test $ git s
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git checkout master
M   testing
Switched to branch 'master'

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

Знаете ли вы, есть ли способ сделать это?

knoopx
источник
1
Хотя есть более простое решение вашей проблемы, не могли бы вы указать, чем полученный результат отличается от того, что вы хотели?
Готье
2
выполнив вышеизложенное или ответы внизу, незафиксированные изменения будут как в основной, так и в новой ветви. Я хочу, чтобы они были только в новой ветке, поэтому я могу проверить мастер и работать над другой вещью, не
меняя
1
см. мой отредактированный ответ. Вам нужно зафиксировать свои локальные изменения в новой ветке, если вы хотите оформить чистый мастер. Локальные изменения - это только различия между текущей HEAD и вашими файлами на диске. Эти изменения в локальных файлах не являются версионными, вам нужно указать git сохранить их где-нибудь, если вы хотите получить их позже.
Готье

Ответы:

1207

Не надо копить.

git checkout -b new_branch_name

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

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

Вы смущены, потому checkout masterчто не отменяете ваши изменения?

Поскольку изменения носят только локальный характер, git не хочет, чтобы вы потеряли их слишком легко. При смене ветки git не перезаписывает ваши локальные изменения. Результат вашего checkout master:

M   testing

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

Если вы действительно хотите отменить локальные изменения, вы должны принудительно оформить заказ -f.

git checkout master -f

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

Попытайтесь вернуться в свою ветку, зафиксируйте изменения, затем снова проверьте мастер.

git checkout new_branch
git commit -a -m"edited"
git checkout master
git status

Вы должны получить Mсообщение после первой проверки, но не после checkout master, и git statusне показывать измененные файлы.

Редактировать, чтобы убрать путаницу с рабочим каталогом (локальные файлы).

В ответ на ваш первый комментарий, локальные изменения просто ... ну, локальные. Git не сохраняет их автоматически, вы должны сообщить об этом, чтобы сохранить их на потом. Если вы внесете изменения и не будете явно фиксировать или хранить их, git не будет их версиями. Если вы измените HEAD ( checkout master), локальные изменения не будут перезаписаны, поскольку не сохранены.

Готье
источник
32
Смущает то, что на странице git checkoutруководства git говорится: «Обновляет файлы в рабочем дереве, чтобы они соответствовали версии в индексе или указанном дереве». Это предполагает, что ваши изменения в вашей файловой системе будут УТВЕРЖДЕНЫ после этого. Без шансов вернуть их. Даже если вы скажете, что они не будут, это все равно оставляет очень плохое предчувствие. Я не доверяю этому вообще . Либо документация действительно плохая, либо поведение git по умолчанию действительно опасно. Не нужно полагаться на какую-то «автоматическую» эвристику, чтобы обнаружить, что в этом случае вы не хотите терять свои изменения.
Evi1M4chine
16
Если вы извлекаете коммит, который перезаписывает ваши локальные изменения (если история между текущим коммитом и целевым коммитом затрагивает ваши локально измененные файлы), git отказывается. Только если checkoutне вступает в конфликт с вашими локальными изменениями, оформление заказа работает и оставляет локальные изменения в покое. Я понимаю, что плохое предчувствие, хотя на странице руководства может быть сказано «Обновляет неизмененные файлы в рабочем дереве». С другой стороны, Git не слишком легко теряет локальные изменения. git checkoutлибо позволяет вашим локальным изменениям в одиночку, либо отказывается в случае конфликта.
Готье
1
хорошо, как я мог бы оформить заказ в другой филиал, не внося туда локальные изменения?
ス レ ッ ク ス
5
@ Алекс git checkout <other_branch> -f. Вы потеряете свои локальные изменения без предупреждения.
Готье
2
@ Evi1M4chine Первый. Документация является очень плохо.
Qwertie
62

Пытаться:

git stash
git checkout -b new-branch
git stash apply
Грант Лимберг
источник
6
Отличается ли это от простого выполнения «git checkout -b new-branch»?
Адриан Муат
Я не думаю, что это было, когда ответ был изначально написан, но я могу ошибаться. К сожалению, в связи с моими рабочими обстоятельствами я уже несколько лет пользуюсь перфомансом, поэтому сейчас не могу подтвердить его точность.
Грант Лимберг
6
Или вместо двух последних шагов: git stash branch new-branch
rethab
1
git stash больше не требуется
kory
Когда у вас уже есть ветвь, в которую вы хотите поместить все свои вещи, stash имеет смысл для меня: (В конце концов, git fetch --all; чтобы получить удаленную ветку в исходном коде) git stash; Git Checkout <существующий филиал>; git stash применить;
Paolof76
24

Вы можете сделать две вещи:

git checkout -b sillyname
git commit -am "silly message"
git checkout - 

или

git stash -u
git branch sillyname stash@{0}

( git checkout -<- тире - это ярлык для предыдущей ветви, на которой вы были)

( git stash -u<- -uозначает, что он также принимает неустановленные изменения)

Pylinux
источник
7

Если вы используете клиент GitHub для Windows (как и я), и вы находитесь в ситуации внесения незафиксированных изменений, которые вы хотите переместить в новую ветку, вы можете просто «Создать новую ветку» через клиент GitHub. Он переключится на вновь созданную ветку и сохранит ваши изменения.

введите описание изображения здесь

Тод Бердсолл
источник
который хранит изменения перед созданием новой ветки, поэтому не сохраняет их (версия 223 для Mac OS)
Фернандо Гальего,
2

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

git checkout -b branch_name

Это создаст новую ветку из вашей текущей ветки (при условии, что она является основной), скопирует незафиксированные изменения и переключится на новую ветку.

Зафиксируйте ваши изменения в новой ветке.

git commit -m "First commit"

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

git push --set-upstream origin feature/feature/NEWBRANCH

Как только вы нажмете эту команду, на удаленном будет создана новая ветка, а ваша новая локальная ветвь будет удалена.

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

git checkout master -f

Это исключит любые незавершенные локальные изменения при оформлении заказа.

инакомыслящий
источник
Чем этот ответ отличается от принятого?
Кометен
Хотя есть некоторые совпадения с принятым ответом, это обеспечивает простое пошаговое руководство, а также включает операции, необходимые для удаленного продвижения новой ветви. Просто, понятно и полезно.
Кьяртан
Этот ответ ясен и очень мне помог.
Вадим
0

В последнем клиенте GitHub для Windows , если у вас есть незафиксированные изменения, и выберите создание новой ветви.
Он подскажет вам, как справиться с этим точным сценарием:

введите описание изображения здесь

То же самое относится, если вы просто переключаете ветку тоже.

Джерри Додж
источник