Страницы

Поиск по вопросам

четверг, 9 января 2020 г.

Как из некоторых снимков сделать отдельную ветку?

#git




Есть существующая старая ветка old в которой вся история из результирующих и промежуточных
снимков. Необходимо выбрать из неё только результирующие снимки и создать на их основе
отдельную «чистую» ветку, например, master.
Решение не обязательно должно соответствовать рисункам, возможно, есть более грамотный
вариант, не знаю.
Рис. 1 — старая ветка.
Рис. 2 — вариант со слиянием.
Рис. 3 — вариант с копированием.
Чёрные — результирующие снимки.
Белые — промежуточные снимки.
    


Ответы

Ответ 1



Как работать, чтобы такая проблема не возникала? «Промежуточные» коммиты нужны и полезны. Очень удобно бывает сохраниться где-то посреди разработки: чтобы попробовать другое решение, чтобы перенести работу на другую машину, просто для спокойствия. Но в итоговой истории они не очень-то интересны. Более того, я лично не хотел бы, чтобы кто-то через месяцы и годы смотрел, как я изобретал велосипеды, писал по строчке в час и делал дурацкие ошибки. Нет, я хочу один финальный коммит, как будто я сел, возложил руки на клавиатуру и создал шедевр. Возможно, вам тоже так будет удобнее. Что делать-то? 1. Используйте фичеветки (feature branches) Для работы над каждой задачей делайте отдельную ветку от master. Делайте в ней сколько душе угодно коммитов. Когда результат будет готов — вы сможете собрать все эти коммиты в один или несколько осмысленных (инструкция ниже) и замержить в master. Мержить рекомендую с --no-ff. Так получается более информативная история: видно, где закончились коммиты одной фичи и начались коммиты другой. Подробнее о фичеветках. Про разные модели работы, в том числе с фичеветками. 2. Пользуйтесь commit --amend для промежуточных коммитов Исправили одну строчку в фичеветке и снова нужно сделать коммит? Проще переписать старый. git add path/filename git commit --amend --no-edit Здесь --no-edit означает, что мы не хотим менять сообщение коммита — оставим старое. Важно: Нужен хотя бы один новый коммит в ветке, который вы будете переписывать. Если вы только что сделали новую ветку от master, пока что нельзя делать --amend. Иначе вы перепишете коммит из master. Важно: commit --amend, rebase -i и другие операции по переписыванию истории нельзя выполнять в общих (стабильных) ветках вроде master. Как объединить коммиты по группам в новой ветке? Предположим, у нас есть такая история коммитов. «Промежуточные» коммиты обозначены как bullshit, а «результативные» — result x. Самый новый коммит — сверху. git log --oneline --graph --decorate * 71e8ed5 (HEAD -> oldbranch) result 2 * 0955502 bullshit * cf30c6f bullshit * d590b3d result 1 * 8266a62 bullshit * ce5b35c bullshit Пересобрать их в более красивую (что очень субъективно) историю нам поможет команда rebase -i. Сначала сделаем новую ветку, в которой будет результат операции. git checkout -b newbranch Поскольку здесь мы хотим заребейзить всю ветку целиком, добавляем --root. git rebase -i --root Если нужно переписать историю только до какого-то коммита (не включая его), указываем хеш этого коммита. git rebase -i ce5b35c Открывается редактор с вот таким содержимым. Здесь порядок коммитов обратный: самый новый коммит — снизу. pick ce5b35c bullshit pick 8266a62 bullshit pick d590b3d result 1 pick cf30c6f bullshit pick 0955502 bullshit pick 71e8ed5 result 2 # Rebase 71e8ed5 onto f7569aa (6 commands) ... Что в этой ситуации можно сделать с коммитами? Нам интересны две команды: # p, pick = use commit # оставить коммит как есть # s, squash = use commit, but meld into previous commit # слить содержимое коммита с ПРЕДЫДУЩИМ коммитом Объединяем (squash) коммиты группами: первый «промежуточный» после каждого результата станет основой нового результата. pick ce5b35c bullshit s 8266a62 bullshit s d590b3d result 1 pick cf30c6f bullshit s 0955502 bullshit s 71e8ed5 result 2 Когда вы сохраните этот текст и выйдете из редактора, откроется новый, с текстом сообщения для нового коммита result 1, потом для result 2 и так далее — столько раз, сколько коммитов вы хотите в итоге оставить. Первым будет самый старый, последним — самый новый. По умолчанию вам предлагается вот такой шаблон: # This is a combination of 3 commits. # This is the 1st commit message: bullshit # This is the commit message #2: bullshit # This is the commit message #3: result 1 # Please enter the commit message for your changes. Lines starting Когда вы отредактируете и сохраните все новые сообщения, rebase -i завершится. Получится примерно такая история: * 588a7ac (HEAD -> newbranch) result 2 * 2713fda result 1

Комментариев нет:

Отправить комментарий