Git объединить мастер в ветвь функции

Допустим, у нас есть следующая ситуация в git:

  1. Созданный репозиторий:

    mkdir GitTest2
    cd GitTest2
    git init
    
  2. Некоторые изменения в мастере происходят и совершаются.

    echo "On Master" > file
    git commit -a -m "Initial commit"
    
  3. Feature1 разветвлен от мастера, и некоторая работа сделана:

    git branch feature1
    git checkout feature1
    echo "Feature1" > featureFile
    git commit -a -m "Commit for feature1"
    
  4. Тем временем в мастер-коде обнаружена ошибка и установлена ветка хотфикса

    git checkout master
    git branch hotfix1
    git checkout hotfix1
    
  5. Ошибка исправлена в ветке исправлений и объединена с мастером (возможно, после запроса на просмотр/проверки кода):

    echo "Bugfix" > bugfixFile
    git commit -a -m "Bugfix Commit"
    git checkout master
    git merge --no-ff hotfix1
    
  6. Разработка на feature1 продолжается:

    git checkout feature1
    

Теперь мой вопрос: скажем, мне нужно исправление в моей ветке функций, возможно, потому что там также происходит ошибка. Как я могу достичь этого, не дублируя коммиты в моей ветке функций? Я хочу запретить получение двух новых коммитов в моей ветки функций, которые не имеют отношения к реализации функции. Это особенно важно для меня, если я использую Pull Requests: все эти коммиты также будут включены в Pull Request и должны быть рассмотрены, хотя это уже было сделано (так как исправление уже есть в мастере).

Я не могу сделать git merge master --ff-only: "fatal: невозможно выполнить перемотку вперед, прерывание.", Но я не уверен, помогло ли это мне.

Ответ 1

Вы должны иметь возможность перебазировать свою ветку на master:

git checkout feature1
git rebase master

Управляйте всеми конфликтами, которые возникают. Когда вы доберетесь до коммитов с исправлениями ошибок (уже в master), git скажет, что изменений не было и, возможно, они уже были применены. Затем вы продолжаете ребаз (пропуская коммиты уже в мастере) с

git rebase --skip

Если вы выполните git log в своей ветки функций, вы увидите, что фиксация исправления появляется только один раз и в основной части.

Для более подробного обсуждения взгляните на документацию Git по git rebase (https://git-scm.com/docs/git-rebase), которая охватывает именно этот вариант использования.

================ Изменить для дополнительного контекста ====================

Этот ответ был предоставлен специально для вопроса, заданного @theomega, с учетом его конкретной ситуации. Обратите внимание на эту часть:

Я хочу запретить коммиты [...] в моей ветки функций, которые не имеют отношения к реализации функций.

Перебазирование его частной ветки на master - именно то, что даст этот результат. Напротив, слияние master с его веткой точно сделало бы то, чего он конкретно не хочет: добавление коммита, не связанного с реализацией функции, над которой он работает, через его ветку.

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

  • только перебазировать частные ветки (то есть, которые существуют только в вашем локальном репо и не были переданы другим). Перебазировка общих веток "сломает" копии, которые могут иметь другие люди.
  • если вы хотите интегрировать изменения из ветки (будь то master или другая ветвь) в общедоступную ветку (например, вы подтолкнули ветку, чтобы открыть запрос на извлечение, но теперь есть конфликты с master, и вам нужно обновить ветвь для разрешения этих конфликтов) вам нужно объединить их (например, с помощью git merge master как в ответе @Sven).
  • Вы также можете объединить ветки в свои локальные частные ветки, если это ваше предпочтение, но помните, что это приведет к "чужим" коммитам в вашей ветке.

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

Ответ 2

Как объединить ведущую ветвь в ветвь функции? Легко:

git checkout feature1
git merge master

Нет смысла форсировать быстрое переключение вперед, поскольку это невозможно. Вы передали как в ветки функции, так и в главную ветвь. Быстрая перемотка вперед невозможна.

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

Итак, что вы делали прямо в своем рабочем процессе? У вас есть две ветки для работы, ваша ветвь feature1 - это, в основном, "развитая" ветвь в модели gitflow.

Вы создали ветвь исправления от мастера и объединили ее. И теперь вы застряли.

Модель gitflow просит объединить исправление также в ветку devel, которая является "feature1" в вашем случае.

Итак, реальный ответ:

git checkout feature1
git merge --no-ff hotfix1

Это добавляет все изменения, которые были внесены в исправление в ветвь функции, но ТОЛЬКО эти изменения. Они могут конфликтовать с другими изменениями развития в ветки, но они не будут конфликтовать с ведущей веткой, если вы в конечном итоге объедините ветвь функции обратно в мастер.

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

Ответ 3

Основываясь на этой статье, вы должны:

  • создать новую ветку, основанную на новой версии мастера

    git branch -b newmaster

  • объединить вашу старую функциональную ветку в новую

    git checkout newmaster

  • разрешить конфликт в новой ветки функций

Первые две команды могут быть объединены для git checkout -b newmaster

Таким образом, ваша история остается ясной, потому что вам не нужны обратные слияния. И вам не нужно быть очень осторожным, потому что вам не нужен git rebase

Ответ 4

Ответ Zimi описывает этот процесс в целом. Вот специфика:

1) Создайте и переключитесь на новую ветку. Убедитесь, что новая ветвь основана на master, поэтому она будет содержать последние исправления.

git checkout master
git branch feature1_new
git checkout feature1_new

# Or, combined into one command:
git checkout -b feature1_new master

2) После перехода на новую ветку объедините изменения из существующей ветки функции. Это добавит ваши коммиты без дублирования исправлений.

git merge feature1

3) В новой ветке разрешите любые конфликты между вашей функцией и главной ветвью.

Готово! Теперь используйте новую ветку, чтобы продолжить разработку вашей функции.

Ответ 5

Возможно, вы сможете сделать "вишневый выбор", чтобы вытащить точные фиксации, которые вам нужны, в свою ветку функций.

Сделайте git checkout hotfix1, чтобы попасть в ветвь hotfix1. Затем выполните git log, чтобы получить хэш SHA1 (большая последовательность случайных букв и цифр, которые однозначно идентифицируют фиксацию) рассматриваемого коммита. Скопируйте это (или первые 10 или около того символов).

Затем git checkout feature1 вернемся к вашей ветке свойств.

Тогда git cherry-pick <the SHA1 hash that you just copied>

Это приведет к тому, что фиксация и только фиксация произойдет в вашей ветке свойств. Это изменение будет в ветке - вы просто "вишнево" выбрали его. Затем возобновите работу, отредактируйте, зафиксируйте, нажимайте и т.д. На ваш сердечный контент.

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

Ответ 6

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

Сценарий выполняет следующие действия:

  • Переключается на главную ветку
  • Тянет мастер ветку
  • Переключается обратно на вашу текущую ветку
  • Объединяет основную ветку с вашей текущей веткой

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

:: This batch file pulls current master and merges into current branch

@echo off

:: Option to use the batch file outside the repo and pass the repo path as an arg
set repoPath=%1
cd %repoPath%

FOR /F "tokens=*" %%g IN ('git rev-parse --abbrev-ref HEAD') do (SET currentBranch=%%g)

echo current branch is %currentBranch%
echo switching to master
git checkout master
echo.
echo pulling origin master
git pull origin master
echo.
echo switching back to %currentBranch%
git checkout %currentBranch%
echo.
echo attemting merge master into %currentBranch%
git merge master
echo.
echo script finished successfully
PAUSE