Git многократно сжимать сквош

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

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

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

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

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

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

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

a---b---X---G

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

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

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

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

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

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

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

Ответы

Ответ 1

Начиная с

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

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

git checkout [email protected]{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

Ответ 2

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

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

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

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

Да. git merge [commit hash]

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

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

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

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

Ответ 3

вы можете использовать git rebase -i (интерактивный режим) для sqash всех ваших изменений, просто измените строки на 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

Ответ 4

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

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

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

$ git reset --hard

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

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

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

Ответ 5

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

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

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

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