Как запулить изменения из другой ветки
Перейти к содержимому

Как запулить изменения из другой ветки

  • автор:

Как подтянуть изменения из другой ветки?

К примеру, у меня есть ветка feature-1, и я сделал feature-2, унаследовав от первой ветки (feature1 -> feature2). После этого начал работать на второй ветке, однако, спустя время, потребовалось внести изменения в первой ветке. Как мне применить изменения, которые я сделал в первой ветке для второй?

Отслеживать
25.9k 7 7 золотых знаков 31 31 серебряный знак 48 48 бронзовых знаков
задан 30 окт 2020 в 11:39
5 1 1 серебряный знак 2 2 бронзовых знака
если комитов в первой ветке много, то смотрите в сторону rebase, если один, то cherry pick.
30 окт 2020 в 11:45
Может быть git checkout feature2 , git merge feature1 ?
30 окт 2020 в 13:32

1 ответ 1

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

если коммиты, добавленные во вторую ветку, ещё никуда не отправлялись, то самое подходящее средство — это rebase :

$ git checkout feature-2 $ git rebase feature-1 

при этом коммиты, которые добавлены в ветку feature-2 , будут пересозданы «поверх» того коммита, на который указывает указатель feature-1 («ветка» в git — это ведь просто плавающий указатель на коммит).

$ man git-rebase 

Отслеживать
ответ дан 1 ноя 2020 в 12:20
aleksandr barakin aleksandr barakin
67.9k 216 216 золотых знаков 77 77 серебряных знаков 219 219 бронзовых знаков

  • git
  • git-branch
    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.10.27.43697

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Шпаргалка по командам git
Что делать, когда под руками нет SourceTree

У нас есть задача (issue), которую мы планируем сделать. В центральном репозитории создаём ветку для решения задачи. Например, для задачи с номером 234 создаём ветку features/issue-234.

Примечание: префикс features/ влияет на отображение > веток в таких графических клиентах, как Git Extensions и Sourcetree. Ветки, в чьих именах встреыется символ / выглядят как файлы в каталогах. Так, ветка features/issue-234 выглядит как ветка issue-234 в каталоге features.

Так удобно группировать ветки.

Шаг 2

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

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

git fetch 

Чтобы убедиться, что удалённая ветка доступна локально, выполняем команду

git branch -a 

Создаём локальную ветку, которая указывает на удалённую ветку

git checkout -b features/issue-234 origin/features/issue-234 
git checkout -t origin/features/issue-234 

Шаг 3

Далее работаем над задачей в локальной ветке, время от времени фиксируя изменения.

Прежде, чем фиксировать, смотрим, что успели сделать.

git status 
  • Untracked — git не отслеживает изменения в этих файлах и не хранит их.
  • Changes not staged for commit — git отлеживает и хранит эти файлы. Сейчас эти файлы изменены, но git не будет сохранять эти изменения при фиксации.
  • Changes to be committed — файлы изменены и git сохранит эти изменения при следующей фиксации.

Помечаем для фиксации файлы file₁..fileₙ.

git add file₁ . fileₙ 

Помечаем для фиксации все файлы в текущем каталоге и его подкаталогах. Помеченными окажутся в том числе все новые файлы.

git add . 

Фиксируем все файлы, помеченные для фиксации. Git попросит ввести комментарий.

git commit 

Команда git commit -a работает также, как git add . и git commit вместе, за тем исключением, что новые файлы не будут зафиксированы.

Команда git commit -m «Комментарий к коммиту» фиксирует изменения с указанным комментарием, не запуская внешний редактор.

Отправляем изменения в центральный репозиторий.

git push 

Откат изменений

Если вы изменили файлы, но ещё не фиксировали изменения, вы можете изменить отдельные файлы:

git checkout -- file₁ . fileₙ 

Либо вы можете отказить изменения во всех файлах в каталоге и его подкаталогах:

git checkout -- . 

Если вы зафиксировали изменения, но ещё не отправили их в удалённый репозиторий, откатите последнюю фиксацию:

git reset --hard 

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

git revert

Если вы случайно добаили к списку отслеживаемых файлов что-то, что не надо отслеживать, например, временные файлы *.tmp или результаты компиляции *.obj, вы можете удалить их из репозитория:

git rm --cached file₁ . fileₙ 

Без флага —cached git удалит файлы и в репозитории, и на диске. Эта же команда используется, если вы обновили .gitignore и хотите удалить из репозитория файлы, которые соответствуют новым правилам .gitignore:

git rm --cached . git add . 

Первая команда удалит из репозитория всех файлы (оставив их на диске), а вторая снова добавит их в репозиторий. При добавлении git проверит файлы на соответствие шаблонам .gitignore.

Удалить с диска новые файлы

git clean -f -d 

Шаг 4

Решив задачу мы должны слить все изменения в основную ветку — master или main. Это делается через pull request в центральном репозитории. Ставим галочку удалить исходную ветку после слияния, чтобы не пришлось удалять эти ветку вручную.

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

git checkout master 

«Затягиваем» в неё изменения из центрального репозитория.

git fetch 

После изменения можно слить с текущей веткой:

git merge 

После слияния в истории репозитория остаются «следы» — коммиты сначла расходятся, потом снова сходятся. Можно избавиться от следов, склеив все коммиты в одну ветку:

git rebase 
git fetch git merge 

git pull

Команда git pull используется для извлечения и загрузки содержимого из удаленного репозитория и немедленного обновления локального репозитория этим содержимым. Слияние удаленных вышестоящих изменений в локальный репозиторий — это обычное дело в процессе совместной работы на основе Git. Команда git pull на самом деле представляет собой комбинацию двух других команд: git fetch и git merge. На первом этапе git pull выполняется команда git fetch , ограниченная локальной веткой, на которую указывает HEAD . Сразу после загрузки содержимого команда git pull выполняет слияние. Для слитого содержимого создается новый коммит, а указатель HEAD обновляется и переносится на этот новый коммит.

Использование git pull

Порядок действий

Сначала команда git pull запускает команду git fetch для загрузки содержимого из указанного удаленного репозитория. Затем выполняется команда git merge , объединяющая ссылки и указатели удаленного содержимого в новый локальный коммит слияния. Чтобы лучше продемонстрировать процесс извлечения и слияния, рассмотрим пример. Предположим, у нас есть репозиторий с главной веткой main и удаленный репозиторий origin.

В этом сценарии команда git pull загрузит все изменения, начиная с того места, где разошлись локальная и главная ветки. В данном примере это точка E. Команда git pull получит удаленные коммиты из отходящей ветки (т. е. точки A‑B‑C). Затем в процессе запуска команды pull будет создан новый локальный коммит слияния, включающий содержимое новых удаленных коммитов из отходящей ветки.

Окно консоли

Связанные материалы
Расширенный журнал Git
СМ. РЕШЕНИЕ
Изучите Git с помощью Bitbucket Cloud

На вышеприведенной схеме мы видим новый коммит H. Это коммит слияния, в который входит содержимое удаленных коммитов A‑B‑C и который имеет общее сообщение в журнале. Этот пример демонстрирует одну из нескольких стратегий слияния с помощью команды git pull . Чтобы сделать перебазирование, а не коммит слитого содержимого, укажите для команды git pull параметр —rebase . В следующем примере демонстрируется, как работает перебазирование с помощью команды pull. Предположим, что мы находимся в начальной точке нашей первой схемы и выполнили команду git pull —rebase .

Из централизованного репозитория git в локальный репозиторий git

На этой схеме видно, что при перебазировании с помощью команды pull не был создан новый коммит H. Вместо этого удаленные коммиты A‑B‑C были скопированы и добавлены в историю в локальной ветке origin/main перед локальными коммитами E–F–G с перезаписью последних.

Распространенные опции

git pull

Извлечь из указанного удаленного репозитория копию текущей ветки и немедленно слить ее с локальной копией. Эта команда аналогична команде git fetch , после которой следует команда git merge origin/ .

git pull --no-commit 

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

git pull --rebase 

Аналогично предыдущей команде pull, только вместо команды git merge для интеграции удаленной ветки с локальной веткой используется команда git rebase .

git pull --verbose

Во время выполнения команды pull выдает подробный вывод о загружаемом содержимом и информацию о слиянии.

Обсуждение git pull

Команду git pull можно представить как версию команды svn update , только применимую в системе Git. Это простой способ синхронизировать локальный репозиторий с вышестоящими изменениями. На диаграмме ниже даны пояснения к каждому шагу процесса выполнения команды pull.

Сначала вы думаете, что ваш репозиторий синхронизирован, однако команда git fetch показывает, что с момента последней проверки версия origin ветки main была изменена. Затем команда git merge сразу интегрирует удаленную ветку main в локальную ветку.

Git pull и синхронизация

Команда git pull — одна из множества команд, отвечающих за синхронизацию удаленного содержимого. Команда git remote используется, чтобы указать, на каких удаленных конечных точках будут работать команды синхронизации. Команда git push используется для выгрузки содержимого в удаленный репозиторий.

Команду git fetch можно перепутать с командой git pull . Обе они используются для загрузки удаленного содержимого, но при этом git pull и git fetch значительно различаются по уровню безопасности. Команду git fetch можно считать «безопасным» вариантом, а git pull — «небезопасным». Команда git fetch загружает удаленное содержимое, но не изменяет состояние локального репозитория, в то время как git pull загружает удаленное содержимое и сразу пытается изменить состояние локального репозитория, чтобы оно соответствовало этому содержимому. Это может привести к возникновению непредумышленного конфликта в локальном репозитории.

Сравнение pull и rebase

Параметр —rebase можно использовать, чтобы сохранить линейную историю и избежать ненужных коммитов слияния. Многие разработчики предпочитают выполнять перебазирование, а не слияние, как бы заявляя: «Я хочу, чтобы мои изменения добавились поверх всех остальных». В этом смысле команда git pull с флагом —rebase больше похожа на команду svn update , чем на простую команду git pull .

На самом деле команда pull с опцией —rebase используется в рабочем процессе настолько часто, что для нее существует выделенная опция конфигурации:

git config --global branch.autosetuprebase always

После выполнения этой команды все команды git pull будут интегрироваться с помощью команды git rebase , а не git merge .

Примеры использования git pull

В нижеприведенных примерах показано, как использовать команду git pull в общих сценариях.

Поведение по умолчанию

git pull

Вызов команды git pull по умолчанию эквивалентен выполнению команд git fetch origin HEAD и git merge HEAD , где HEAD — это указатель на текущую ветку.

Команда git pull на удаленных ветках

git checkout new_feature
git pull

В этом примере сначала создается ветка и происходит переключение на нее. После этого выполняется команда git pull , в которой передается удаленный репозиторий . Это приводит к неявной загрузке (выполнению команды pull) ветки newfeature из удаленного репозитория . Как только загрузка завершается, начинается выполнение команды git merge .

Перебазирование с помощью git pull вместо слияния

В следующем примере показано, как выполнить синхронизацию с главной веткой main центрального репозитория, используя перебазирование.

git checkout main
git pull --rebase origin

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

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

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

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