Как перейти из ветки master в ветку dev
Перейти к содержимому

Как перейти из ветки master в ветку dev

  • автор:

3.3 Ветвление в Git — Управление ветками

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

Команда git branch делает несколько больше, чем просто создаёт и удаляет ветки. При запуске без параметров, вы получите простой список имеющихся у вас веток:

$ git branch iss53 * master testing

Обратите внимание на символ * , стоящий перед веткой master : он указывает на ветку, на которой вы находитесь в настоящий момент (т. е. ветку, на которую указывает HEAD ). Это означает, что если вы сейчас сделаете коммит, ветка master переместится вперёд в соответствии с вашими последними изменениями. Чтобы посмотреть последний коммит на каждой из веток, выполните команду git branch -v :

$ git branch -v iss53 93b412c Fix javascript issue * master 7a98805 Merge branch 'iss53' testing 782fd34 Add scott to the author list in the readme

Опции —merged и —no-merged могут отфильтровать этот список для вывода только тех веток, которые слиты или ещё не слиты в текущую ветку. Чтобы посмотреть те ветки, которые вы уже слили с текущей, можете выполнить команду git branch —merged :

$ git branch --merged iss53 * master

Ветка iss53 присутствует в этом списке потому что вы ранее слили её в master . Те ветки из этого списка, перед которыми нет символа * , можно смело удалять командой git branch -d ; наработки из этих веток уже включены в другую ветку, так что ничего не потеряется.

Чтобы увидеть все ветки, содержащие наработки, которые вы пока ещё не слили в текущую ветку, выполните команду git branch —no-merged :

$ git branch --no-merged testing

Вы увидите оставшуюся ветку. Так как она содержит ещё не слитые наработки, попытка удалить её командой git branch -d приведёт к ошибке:

$ git branch -d testing error: The branch 'testing' is not fully merged. If you are sure you want to delete it, run 'git branch -D testing'.

Если вы действительно хотите удалить ветку вместе со всеми наработками, используйте опцию -D , как указано в подсказке.

Если в качестве аргумента не указан коммит или ветка, то опции —merged и —no-merged покажут что уже слито или не слито с вашей текущей веткой соответственно.

Вы всегда можете указать дополнительный аргумент для вывода той же информации, но относительно указанной ветки предварительно не извлекая и не переходя на неё.

$ git checkout testing $ git branch --no-merged master topicA featureB

Переименование ветки

Не переименовывайте ветки, которые всё ещё используются другими участниками. Не переименовывайте ветку в master/main/mainline, не прочитав раздел «Изменение имени главной ветки».

Предположим, у вас есть ветка с именем bad-branch-name , и вы хотите изменить её на corrected-branch-name , сохранив при этом всю историю. Вместе с этим, вы также хотите изменить имя ветки на удалённом сервере (GitHub, GitLab или другой сервер). Как это сделать?

Переименуйте ветку локально с помощью команды git branch —move :

$ git branch --move bad-branch-name corrected-branch-name

Ветка bad-branch-name будет переименована в corrected-branch-name , но это изменение пока только локальное. Чтобы все остальные увидели исправленную ветку в удалённом репозитории, отправьте её туда:

$ git push --set-upstream origin corrected-branch-name

Теперь проверим, где мы сейчас находимся:

$ git branch --all * corrected-branch-name main remotes/origin/bad-branch-name remotes/origin/corrected-branch-name remotes/origin/main

Обратите внимание, что текущая ветка corrected-branch-name , которая также присутствует и на удалённом сервере. Однако, старая ветка всё ещё по-прежнему там, но её можно удалить с помощью команды:

$ git push origin --delete bad-branch-name

Теперь старое имя ветки полностью заменено исправленным.

Изменение имени главной ветки

Предупреждение

Изменение имени ветки, например master/main/mainline/default, сломает интеграции, службы, вспомогательные утилиты и скрипты сборки, которые использует ваш репозиторий. Прежде чем сделать это, обязательно проконсультируйтесь с коллегами. Также убедитесь, что вы выполнили тщательный поиск в своём репозитории и обновили все ссылки на старое имя ветки в вашем коде или скриптах.

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

$ git branch --move master main

После этого, локальной ветки master больше не существует, потому что она была переименована в ветку main .

Чтобы все остальные могли видеть новую ветку main , вам нужно отправить её в общий репозиторий. Это делает переименованную ветку доступной в удалённом репозитории.

$ git push --set-upstream origin main

В итоге, состояние репозитория становится следующим:

$ git branch --all * main remotes/origin/HEAD -> origin/master remotes/origin/main remotes/origin/master

Ваша локальная ветка master исчезла, так как она заменена веткой main . Ветка main доступна в удалённом репозитории. Старая ветка master всё ещё присутствует в удалённом репозитории. Остальные участники будут продолжать использовать ветку master в качестве основы для своей работы, пока вы не совершите ряд дополнительных действий.

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

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

После того, как вы выполнили все эти задачи и уверены, что ветка main работает так же, как ветка master , вы можете удалить ветку master :

$ git push origin --delete master

Слить ветку master и main

Создал проект и главная была ветка master, сделал коммиты, запушил. Получается в ветке main лежит только .gitignore, а на компе видна только ветка master. Как их слить в main?

Отслеживать
задан 30 окт 2020 в 6:03
25 1 1 золотой знак 1 1 серебряный знак 4 4 бронзовых знака

ничего не понятно. а) упоминаются три ветки: master , Master , main . откуда они все взялись? б) откуда взялся файл .gitignore в ветке main ? в) что именно у вас не получается?

30 окт 2020 в 6:14

1) ветки две: master, main 2) .gitignore создался при создании репрозитория через гитхаб. потом я через git init и push свой репрозиторий запушил в тот. 3) Не знаю как получить эту ветку main, чтобы слить ее с master

30 окт 2020 в 7:02
$ git checkout main
30 окт 2020 в 7:06

3 ответа 3

Сортировка: Сброс на вариант по умолчанию

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

следующая проблема, с которой вы столкнулись, проистекает из сумасбродства (моё оценочное суждение) владельцев сервера github.com — в то время как программа git создаёт по умолчанию ветку с именем master , не так давно они решили у себя на сервере создавать ветку с именем main . будем исходить из предположения, что вы согласны пойти у них на поводу и использовать имя main как локально, так и в копии вашего хранилища на их сервере. это допущение номер два.

итак, что у вас есть?

  1. в локальном хранилище ветка master с одним или несколькими коммитами.
  2. в хранилище на github.com ветка main с одним коммитом, в котором создан автоматически сгенерированный файл .gitignore .

что хотим получить?

  1. локальное хранилище с веткой main , содержащее как коммиты из локальной ветки master , так и коммит, созданный в ветке main на сервере github.com
  2. идентичную картину и в хранилище на сервере github.com

    если ещё не подключили к своему локальному хранилищу то хранилище, что создали на сервере, то подключите и заберите оттуда информацию:

$ git remote add origin [email protected]:имя-вашей-учётной-записи/имя-хранилища $ git fetch --all 
$ git checkout master 
$ git cherry-pick origin/main 
$ git branch -f main master 
$ git checkout main 
$ git branch -D master 
$ git push -f -u origin main 

на этом всё. доп. чтение:

  • $ man git-remote
  • $ man git-fetch
  • $ man git-checkout
  • $ man git-cherry-pick
  • $ man git-branch
  • $ man git-push

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

19. Переключение веток

Просто используйте команду git switch для переключения между ветками.

Выполните
git switch main cat hello.html 
Результат
$ git switch main Switched to branch 'main' $ cat hello.html    

Hello, World!

Теперь мы находимся в ветке main . Как видите, в hello.html нет никаких следов style.css . Не волнуйтесь, эти изменения все еще есть в репозитории, но мы не можем увидеть их из ветки main .

02 Вернемся к ветке style

Выполните
git switch style cat hello.html 
Результат
$ git switch style Switched to branch 'style' $ cat hello.html    "text/css" rel="stylesheet" media="all" href="style.css" />   

Hello, World!

Мы вернулись к ветке style . Как видите, наши изменения, связанные с CSS, присутствуют.

Как в git заменить master на другую ветку без использования push —force (перенос стейта одной ветки на другую)

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

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

Итак: есть 2 ветки, запоротый master и новый newMaster .

UPD: оказалось что практически тоже самое можно сделать одной командой https://git-scm.com/docs/git-merge#Documentation/git-merge.txt-ours-1, находясь на newMaster сделать:

git merge -s ours master 

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

Конец upd.

Задача: использовать состояние целиком из newMaster , но продолжить разработку из master . Т.е. как бы мердж, но не мердж. Можно бы сделать через перевешивания мастера на новую ветку и push —force но это запрещено на нашем гите и создаст проблемы коллегам. Поэтому сделаем так, будто разработка в ветке была замержена в мастер.

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

Все подобные операции я провожу собирая и подписывая все хешики команд в блокнотик рядом.

Если вы не тимлид, спросите тимлида, перед тем как это делать. Совсем намертво сломать ничего не сломается, коммиты в master после отделения newMaster , останутся только в истории, но не потеряются совсем.

Самое главное знание

git оперирует не изменениями, а состояниями файлов, поэтому мы можем сконструировать коммит с нужным нам состоянием:

Для начала установим хеши коммитов на которые смотрят наши бранчи:

git rev-parse master 193cf791417f6fb8a48fd8eb123c1bd53ffac10a
git rev-parse newMaster 338cb13ada6efdbd9a3610adeab7700fb1ba91d2

Перейдём в ветку newMaster:

git checkout newMaster Switched to branch 'newMaster' Your branch is up to date with 'origin/newMaster'.

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

git cat-file -p 338cb13ada6efdbd9a3610adeab7700fb1ba91d2 tree 6fac19212aba1d31d2df5ad6498cdb4b111a2022 parent f719d58b010c0b70e8fdefcff2ecbc3e7fddda54 author ***** <*****>1699870138 +0300 committer ***** <*****>1699870138 +0300 Bindable event removed

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

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

  1. Содержать нужное нам состояние файлов (дерево)
  2. Быть мердж коммитом: т.е. иметь два предка, коммит из поломанного мастера и коммит из нового мастера, порядок указания предков определяет как графические утилиты будут показывать направление мерджа, будет выглядеть как мердж второго аргумента в первый.
  3. обладать нужным нам мессаджем
git commit-tree 6fac19212aba1d31d2df5ad6498cdb4b111a2022 -p 193cf791417f6fb8a48fd8eb123c1bd53ffac10a -p 338cb13ada6efdbd9a3610adeab7700fb1ba91d2 -m "manual force commit newMaster to master with fake merge, because old master is obsolete" 74092e5acd734a7df459ca4b08f4e88f451096f9

git commit-tree создал для нас коммит и вернул его хеш: 74092e5acd734a7df459ca4b08f4e88f451096f9 который не находится ни в каком бранче. Если на этом этапе просто забить на всё и забыть, то в результате push этот коммит никуда не будет отправлен, т.к. на него нет ссылок с действующих бранчей, и через некоторое время git gc его сожрёт. Теперь надо сказать что наш старый мастер смотрит на этот коммит.

git branch -f master 74092e5acd734a7df459ca4b08f4e88f451096f9

Как мы помним, выше мы переключались на newMaster , именно для того чтобы branch -f master сработал, ибо запрещено менять ветку на который сейчас находишься.

Готово, теперь master содержит абсолютно легитимный мерж коммит, который с точки зрения гита продолжает историю мастера и является мерж коммитом из newMaster . Теперь можно переключиться на мастер и запушить.

git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 26 commits. (use "git push" to publish your local commits) 

И здесь мы видим что в master появились 26 коммитов которые нужно запушить, ровно так выглядит мердж ветки.

git push Locking support detected on remote "origin". Consider enabling it with: $ git config lfs.https://*****.git/info/lfs.locksverify true Enumerating objects: 1, done. Counting objects: 100% (1/1), done. Writing objects: 100% (1/1), 255 bytes | 255.00 KiB/s, done. Total 1 (delta 0), reused 0 (delta 0) To *****.git 193cf79..74092e5 master -> master 

Здесь мы видим что по факту ушёл всего один объект, тот самый наш коммит, который содержит ссылку на уже существующее дерево.

Поскольку этот коммит имеет в предках последний коммит из master всё проходит нормально

Ссылки на документацию по применённым командам:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *