Git Merge Squash несколько раз

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

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

          X -------------------G стабильный
         /                   /
    a---b---c---d---e---f---g разработка

Поскольку у G есть родительский элемент в ветви разработки, я получаю всю историю ветви разработки (объекты данных для c, d, e, f и g) в моем репозитории, которая мне не интересна (X такой же, как б, с некоторым переименованием файла).

Поэтому я пытался git merge --squash переход от ветки разработки к стабильной ветке. Первое такое объединение и фиксация прошли нормально, результаты были такими, как ожидалось (хороший журнал изменений в сообщении фиксации, никакого отношения к ветке разработки):

 X -------------------G стабильный
         /                   
    a --- b --- c --- d --- e --- f --- g разработка

После того, как я вытаскиваю эту сжатую стабильную ветвь, я получаю это в своем хранилище, что я и хочу:

--- --- Х Ь ---G

Но второе слияние не удалось (потому что git не мог узнать, сколько я уже слил и запутался).

  • Можно ли как-то записать слияние, не производя "коммит слияния" с двумя родителями?
  • Или можно сказать git слить только определенный "диапазон" ревизий, как в SVN?
  • Или возможно ли выполнить нормальное слияние без необходимости загружать все ссылки из другой ветки при извлечении?
  • Или я должен предоставить собственный драйвер слияния для рассматриваемых файлов, который просто переименовывает "их" версию в "нашу", тем самым разрешая конфликты? Я все еще боюсь, что --squash всегда буду пытаться объединить всю историю, вплоть до общего родителя, решив только половину моей проблемы.

Обновление: перебазирование

Если я правильно понимаю перебазирование, я получу следующее:

                              Х стабильный
                             /
    a --- b --- c --- d --- e --- f --- g разработка

Это дает мне все данные, которые меня не интересуют (c, d, e, f), и в качестве бонуса я потеряю информацию, что b была стабильной версией в ветке.

Каждая версия разработки добавляет около 5 МБ к размеру репозитория (а переупаковка всего репо сокращает его всего на 10%), "стабильная" ветвь поставляется почти бесплатно (данные уже есть). Я хочу вытащить одну новую ревизию из стабильной ветви, чтобы вытащить только новые 5 МБ, но вместо этого обновление с X на G загружает 25 МБ, потому что я почему-то не могу сказать, что меня не волнует содержание c, d, е и ф.

5 ответов

Решение

Начиная с

      X stable
     /                   
a---b---c---d---e---f---g development

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

git checkout development@{0}  # get working tree from "development", detach HEAD
git reset --soft stable  # reposition detached HEAD on "stable"
git commit  # enter the appropriate commit message
git branch temp  # create a temporary branch "temp" at HEAD
git checkout temp  # get on the new temporary branch
git branch -M stable  # rename "temp" to "stable"

так что вы в конечном итоге:

      X-------------------G stable
     /                   
a---b---c---d---e---f---g development

Если вы продолжите работу над "развитием", например,

      X-------------------G stable
     /                   
a---b---c---d---e---f---g---h---i---j development

Вы можете повторить те же команды git, что и выше, и в итоге получите:

      X-------------------G-----------J stable
     /                   
a---b---c---d---e---f---g---h---i---j development

Это не правильное место для использования merge --squash, Хорошее место для его использования - одноразовая ветка тем, которую вы собираетесь объединить с основной веткой, а затем избавиться от нее. Вся разработка, выполненная в ветке темы, показана как одна фиксация в основной ветке. В вашей ситуации вы должны слиться с веткой разработки в обычном режиме, а затем использовать git-rebase --interactive раздавить коммиты вы хотите.

Можно ли как-то записать слияние, не производя "коммит слияния" с двумя родителями?

Если я правильно понял вопрос, нет. Абсолютно нет.

Можно ли сказать git объединять только определенный "диапазон" ревизий, как в SVN?

Да. git merge [commit hash]

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

Смотрите ответ на предыдущий вопрос.

Или я должен предоставить собственный драйвер слияния для рассматриваемых файлов, который просто переименовывает "их" версию в "нашу", тем самым разрешая конфликты? Я все еще боюсь, что --squash всегда будет пытаться объединить всю историю, вплоть до общего родителя, решая только половину моей проблемы.

Нет! Просто не используйте git merge --squash, Это не то место, где можно его использовать!

Вы могли бы использовать git rebase -i (интерактивный режим), чтобы исправить все ваши изменения, просто измените строки на m или же meld (обновление: для более новых версий Git s или же squash)

у вас будет один коммит, который вы сможете объединить. Если вы хотите, чтобы каждый ваш шаг был зарезервирован, вы должны создать еще одну ветку в вашей хакерской ветке, прежде чем делать ребаз, это можно сделать с помощью git branch small-dirty-changes-i-don’t-want-anybody-to-see

все это должно быть сделано перед попыткой слияния; шаг за шагом:

# on branch "hacking": hack commit hack commit hack commit

# create a reference to your history
$ git branch dirty-history

# sqash your commits by setting all lines to "meld"
$ git rebase -i

# checkout master or the branch you want to merge to
$ git checkout master

# merge your squashed commit
$ git merge hacking
# or: $ git pull hacking

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

$ git checkout stable 
$ git diff stable development | git apply --index -   
$ git commit

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

$ git reset --hard

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

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

Если вас это беспокоит, каждый раз, когда вы фиксируете стабильную версию, вы можете поместить объединенный диапазон хэшей разработки в сообщение фиксации. Таким образом, у вас есть некоторая запись, если вам когда-нибудь понадобится отказаться.

Я новичок в git, но похоже, что --squash - это то, что вы хотите, вам просто нужно по-другому обработать ветку.

$ git merge --squash development
$ git branch -d development
$ git checkout -b development
# continue work on development branch

Это, по сути, усечет историю ветки разработки, и следующее слияние будет только тем, что вы хотели. Глядя на справочную страницу, кажется, git branch -f development может сделать то же самое, что и удаление и воссоздание ветви.

Как я уже сказал, я довольно новичок в Git, поэтому я хотел бы получить некоторые отзывы об этой идее.

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