Смущен git checkout

Я новичок в мерзости и пытаюсь обернуть голову вокруг работы веток. Согласно документации Git Checkout

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

Поэтому, насколько я понимаю, файлы в моем каталоге, в котором я работаю (файл, в котором я выполнял git init), должны меняться в зависимости от того, в какой ветке я нахожусь. Я запутался, потому что этого не происходит, когда я меняюсь между ветвями. Изменения, над которыми я работал до того, как переключил ветви, присутствуют в той ветви, на которую я переключился. Я делаю что-то не так или Git Checkout не работает таким образом, и я просто неправильно понимаю документы?

2 ответа

Решение

У Git есть общая проблема - собрать в одну команду восемь или десять разных вещей.

git checkout может обновить рабочее дерево, и обычно делает.

Это может измениться где HEAD указывает, а иногда и делает, иногда нет.

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

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

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

$ git clone ...
$ git branch
* master
$

В этот момент вы можете отредактировать некоторые файлы, приступить к работе и только потом понять: "Гах! Я хотел сделать это на ветке develop! "1

Git позволяет вам в этот момент переключаться на (или создавать) ветку develop, сохраняя ваши модификации, при одном условии: переход на develop не требует их уничтожения. Допустим, вы изменили файл f1 и создал новый f2, и теперь вы хотите создать и проверить локальное отделение develop который должен начинаться, и автоматически "отслеживать",2 origin/develop:

$ git checkout develop 

(в очень старых версиях GIT, вы должны записать это git checkout -b develop --track origin/develop).

Давайте также скажем, что файл f1 то же самое на кончиках филиала master и филиал develop,3 Для git это означает, что он может делать эту проверку, потому что он не должен изменять файл f1так что он может оставить ваши существующие изменения в f1 на месте.

Если файл f2 также одинаково в обоих коммитах, или (как в этом случае) не существует ни в одном из них, тогда файлы не будут засорены, и git checkout создаст ваше новое местное отделение develop, модифицируя рабочее дерево для соответствия origin/develop по мере необходимости - и это не включает в себя изменение f1ни удаление f2так что работа, которую вы проделали до сих пор, остается нетронутой.

Это позволяет вам зафиксировать ваши новые изменения в вашем локальном develop,

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


1 Это происходит со мной все время. Много раз я хотел создать новую не отслеживающую ветку, которая немного проще, чем переключение на существующую ветку, но принцип все еще применяется.

2 Это автоматическое отслеживание позволяет вам легче вносить изменения, сделанные другими людьми: как только git заберет их git fetch, Git сообщит вам об изменениях других людей, и позволит вам использовать git merge или же git rebase объединить ваши изменения с их изменениями, без лишних раздумий, чтобы выяснить, чьи изменения идут куда.

3 Поскольку вы новичок в git, такие понятия, как различение "кончика ветви", который является конкретным коммитом, от "ветви", которая на самом деле неоднозначна - есть метки ветвей, а затем есть структуры ветвей, образованные дерево коммитов - это то, что вы обычно должны игнорировать некоторое время. Главное, что нужно отметить, это то, что в репозитории git есть специальный файл с именем HEADи в этом специальном файле git записывает строку ref: refs/heads/master или же ref: refs/heads/develop, чтобы отслеживать, на какой ветке вы находитесь. Так git checkout X напишет ref: refs/heads/X в HEAD как только он переключается на филиал X,

Между тем, другой набор специальных файлов в хранилище сообщает git, что ветка master относится к одному из тех больших уродливых SHA-1, как c06f8d11b75e28328cdc809397eddd768ebeb533, Это "верхушка" ветки master, Когда вы делаете новый коммит на mastergit создает новый коммит "один за старым советом", затем записывает новый SHA-1 в файлы веток, так что master теперь ваш новый коммит.

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

Эта путаница признана Git 2.23.
Git 2.23 (3 квартал 2019 г.) заменитgit checkoutс двумя новыми командами:

См совершают 97ed685, совершает d16dc42, совершает bcba406 (20 июн 2019), совершает 4e43b7f, совершает 1235875, совершают 80f537f, совершает fc991b4, совершает 75f4c7c, совершают 4df3ec6, совершает 2f0896e, совершает a5e5f39, совершает 3a733ce, совершает e3ddd3b, совершает 183fb44, совершает 4058199, зафиксировать a6cfb9b, зафиксировать be8ed50, зафиксировать c9c935f, зафиксировать 46e91b6 (25 апреля 2019 г.) и commit 328c6cb (29 марта 2019 г.), автор: Nguyễn Thái Ngọc Duy (pclouds).
(Слияние Junio ​​C Hamano -gitster- в коммите f496b06, 09 июл 2019)

checkout: разделить часть на новую команду 'switch'

"git checkout"выполнение слишком большого количества действий является источником путаницы для многих пользователей (и иногда это даже кусает старожилов).
Чтобы исправить это, команда будет разделена на две новые: переключение и восстановление. Старая добрая".git checkout"команда все еще здесь и будет, пока она всем (или большинству пользователей) не надоест.

А также:

переключатель: отклонить, если выполняется какая-то операция

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

Новый вариант --ignore-in-progressбыл рассмотрен, но отклонен, потому что не совсем ясно, что должно произойти.
Иногда можно переключиться, безопасно вернуться и продолжить работу. Иногда нет.
Иgit-checkoutповедение автоматически очищается merge / revert / cherry-pick, что делает его еще более запутанным.
См. Это обсуждение.

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

Третий вариант - старый добрый "git checkout", но об этом не упоминается.


Видеть git switch страница руководства

ОПИСАНИЕ

Переключиться на указанную ветку.
Рабочее дерево и индекс обновляются в соответствии с веткой.
Все новые коммиты будут добавляться в верхушку этой ветки.

При желании новую ветку можно создать с помощью -c, -C, автоматически из удаленной одноименной ветки (см. --guess) или отсоедините рабочее дерево от любой ветви с помощью --detach, вместе с переключением.

Для переключения ветвей не требуется чистый индекс и рабочее дерево (т.е. никаких различий по сравнению с HEAD).
Однако операция прерывается, если операция приводит к потере локальных изменений, если иное не указано в--discard-changes или --merge.


ПРИМЕРЫ

Следующая команда переключается на "master" ветвь:

$ git switch master

После работы в неправильной ветке переключение на правильную ветку будет выполнено с помощью:

$ git switch mytopic

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

$ git switch mytopic
error: You have local changes to 'frotz'; not switching branches.

Вы можете дать -m флаг к команде, которая попытается выполнить трехстороннее слияние:

$ git switch -m mytopic
Auto-merging frotz

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

Чтобы вернуться к предыдущей ветке до того, как мы перешли на mytopic (т.е. "master" ветвь):

$ git switch -

Вы можете вырастить новую ветку из любого коммита.
Например, переключитесь на "HEAD~3"и создать ветку"fixup":

$ git switch -c fixup HEAD~3
Switched to a new branch 'fixup'

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

$ git switch new-topic
Branch 'new-topic' set up to track remote branch 'new-topic' from 'origin'
Switched to a new branch 'new-topic'

Чтобы проверить фиксацию HEAD~3 для временной проверки или эксперимента без создания новой ветки:

$ git switch --detach HEAD~3
HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits'

Если окажется, что все, что вы сделали, стоит сохранить, вы всегда можете создать для него новое имя (не переключаясь):

$ git switch -c good-surprises

Обратите внимание на сообщения об ошибках, которые "git switch"упоминает о возможности создания новой ветки",-b/-B"варианты были показаны, где"-c/-Cдолжны быть, что было исправлено в Git 2.27 (второй квартал 2020 г.).

См. Commit 7c16ef7 (30 апреля 2020 г.) Дентон Лю (Denton-L).
(Слияние Junio ​​C Hamano -gitster- в коммите f4675f3, 08 мая 2020 г.)

switch: исправить ошибки и комментарии, связанные с -c и -C

Автор отчета: Роберт Симпсон
Подписано: Дентон Лю
Рецензент: Тейлор Блау

В d787d311db ("checkout: разделить его часть на новую команду 'switch'", 2019-03-29, Git v2.23.0-rc0 - слияние указано в пакете №4),git switch команда была создана путем извлечения общих функций cmd_checkout() в checkout_main().

Однако в b7b5fce270 ("switch: лучшие имена для -b а также -B", 2019-03-29, Git v2.23.0-rc0 - слияние указано в пакете №4), параметры создания ветки и принудительного создания для 'switch'были изменены на -c а также -Cсоответственно.

В результате этого сообщения об ошибках и комментарии, которые ранее упоминались -b а также -B стал недействительным для git switch.

Сообщения об ошибках, относящиеся к -b а также -Bиспользуйте вместо этого строку формата, чтобы -c а также -C можно распечатать, когда git switch вызывается.

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

Допустим, вы находитесь в основной ветке и хотите создать ветку "разработка"

Все вместе должно выглядеть так:

** git checkout -b development // создаем и переключаемся на разработку ветки

touch text.txt // создаем документ text.txt

мерзавец добавить. // добавляем text.txt

git commit -m "добавление text.txt"

мастер проверки

И тогда вы не увидите text.txt, так как вы в Мастер

Другие вопросы по тегам