Комментарии 33
Так что теперь нельзя будет вливать develop в свою ветку без геморроя? Или я чего-то недопонял?
Все можно. Просто по умолчанию теперь оно будет просить отредактировать сообщение коммита (как при git commit после разрешения конфликта в merge). Это поведение можно подавить ключом --no-edit или переменной окружения MERGE_AUTOEDIT.
Основная задумка — заставить людей писать почему они делают тот или иной merge (не все направления слияний одинаково полезны)
Почему это важно — новое поведение по-умолчанию может сломать старые скрипты
Основная задумка — заставить людей писать почему они делают тот или иной merge (не все направления слияний одинаково полезны)
Почему это важно — новое поведение по-умолчанию может сломать старые скрипты
Ага. Ну в принципе да, полезная фича. Особенно если кодер вливает соседнюю ветку (если вливаемая ветка не develop) в свою — мне как проверяющему коммиты\мержи\и т.п. было бы интересно узнать зачем чел это сделал.
Да. А еще может люди задумаются, что иногда сделать, к примеру rebase своей фичи полезнее чем мерджить апстрим в нее
а чем полезнее-то? Ну вот делаю я изменения в file1 который зависит от кода в file2 и file3 и тут народ наделал изменений в file2 допустим и замерджил изменения в общую ветку. И я тогда мерджу общую ветку себе и имею измененный file2. Что ж тут неправильно-то? И что мне в этом случае даст rebase?
Основная идеология работы с ветками — каждая ветка содержит «чистую» одну единицу функциональности. Т.е. то что кто-то в file2 внес изменения, не нужные для работы вашей функциональности не является поводом для слияния.
В то же время человеку осуществляющему merge вашей ветки с апстримом может быть сложно разрешить конфликты (т.к. он не знает вашего кода). В таком случае полезно делать rebase вашей ветки относительно общей, чтобы сохранялись два принципа:
1. В вашей ветке — только коммиты относящиеся к новой одной единице функциональности
2. Ветка без проблем может быть влита в мастер
В то же время человеку осуществляющему merge вашей ветки с апстримом может быть сложно разрешить конфликты (т.к. он не знает вашего кода). В таком случае полезно делать rebase вашей ветки относительно общей, чтобы сохранялись два принципа:
1. В вашей ветке — только коммиты относящиеся к новой одной единице функциональности
2. Ветка без проблем может быть влита в мастер
«каждая ветка содержит «чистую» одну единицу функциональности» — да, да. Тут я понял и со всем могласен. А как быть со случаем когда каждая ветка содержит «чистую» одну единицу функциональности, но только над одной единицей функциональности работает, допустим, 3 человека?
Ну это же гит, ё-маё! Он же ДЕцентрализованный. И никто не запрещает этим разработчикам обмениваться апдейтами напрямую. И только когда функционал готов — кто-то один из них отсывает (ветку/набор патчей/pull request — подставить нужное) тимлиду или кто там у вас главный.
Горячо рекумендую — посмотрите «Linus Torvalds on Git». Оно есть и с русским переводом если что, но в оригинале есть непередаваяемя экспрессия в речи Линуса. В своё время, лично мне именно это видео дало наибольший толчок в понимании гита.
Горячо рекумендую — посмотрите «Linus Torvalds on Git». Оно есть и с русским переводом если что, но в оригинале есть непередаваяемя экспрессия в речи Линуса. В своё время, лично мне именно это видео дало наибольший толчок в понимании гита.
Ну как вегда — rebase даёт «красивую» историю коммитов, не более того.
Кстати, одно из неудобных вещей в git, это то, что когда из master-ветки вливаются изменения в «функциональную» (как бы это ни было неправильно, это часто необходимо), потом просмотр истории коммитов «фукнциональной» ветки (например, в веб-интерфейсе) теряет смысл. Ибо он, действительно, представляет собой свалку несвязанных между собой коммитов. Я плохо знаю устройство git'а изнутри, поэтому не знаю возможно ли это, но было бы неплохо иметь возможно смотреть «чистую» историю ветки. То есть, чтобы показывались коммиты, совершенные только непосредственно в этой ветке.
К сожалению так сделать нельзя. «Ветка» в git — это просто именованный указатель на какой-то коммит (голова ветки). Вычислить принадлежность того или иного коммита в истории этой ветки к «самой ветке» архитектурно невозможно.
Поскольку у нас над «функциональными» ветками обычно работает 1 человек, мы просто делаем rebase ветки относительно апстрима
Поскольку у нас над «функциональными» ветками обычно работает 1 человек, мы просто делаем rebase ветки относительно апстрима
Это было бы возможно, если бы в каждом коммите была некая запись, которая сохраняла название «оригинальной» ветки, в которой был совершен коммит. Такая запись влияла бы только на просмотр истории изменений. Интересно, почему разработчики так не сделали.
Сколько пользуюсь гитом, а что такое rebase так и не разобрался :)
Rebase, мне кажется, проще всего понять, если понаблюдать за тем, как именно он происходит, т.е. за сообщениями, которые выдаёт Гит. В двух словах, rebase ветки feature на ветку master — это:
1. Переместить указатель feature на master.
2. Применить все коммиты, которые были в feature и не были в master, один за другим, как патчи. Одновременно двигать указатель feature.
Этим и достигается линейность истории — одна из основных причин использования rebase вместо merge.
Довольно хорошо rebase расписан в популярной книге Pro Git: progit.org/book/ch3-6.html
(Есть и русская онлайн версия книги)
1. Переместить указатель feature на master.
2. Применить все коммиты, которые были в feature и не были в master, один за другим, как патчи. Одновременно двигать указатель feature.
Этим и достигается линейность истории — одна из основных причин использования rebase вместо merge.
Довольно хорошо rebase расписан в популярной книге Pro Git: progit.org/book/ch3-6.html
(Есть и русская онлайн версия книги)
А rebase патчи жестко накладывает на основную ветку или нет? Опишу ситуацию: ветвимся, в масетере в file1 есть код. Мы с воей ветке резвимся и правим этот код. Кто-то раньше нас вливает в мастер изменения и file1 немного поменялся. И тут мы делаем rebase. Файл умело сольется, как это происходит при мердже или будет заменен нашим патчем?
Если 2 вариант, то rebase не такой уж и безобидный.
Если 2 вариант, то rebase не такой уж и безобидный.
rebase — это тот же merge, просто записывается в историю он так, чтобы история выглядела линейной. Поэтому разрешение конфликтов никто не отменял — если гит не сможет разрулить ваш конфликт автоматически, он попросит вас сделать это вручную.
Ну а вообще я бы рекомендовал перед любыми операциями, которые переписывают историю, делать копию вашего локального репозитория рядом (на всякий случай). Особенно если вы только что познакомились с rebase и еще не знаете, как отменить неудачный rebase, а плюс к этому всему в вашем репозитории много новейших коммитов, бакапа которых нигде нет.
Ну а вообще я бы рекомендовал перед любыми операциями, которые переписывают историю, делать копию вашего локального репозитория рядом (на всякий случай). Особенно если вы только что познакомились с rebase и еще не знаете, как отменить неудачный rebase, а плюс к этому всему в вашем репозитории много новейших коммитов, бакапа которых нигде нет.
> делать копию
Зачем копию?
Это ж git!
И работайте с вашей текущей веткой как хотите.
Зачем копию?
Это ж git!
git br saved_branch
И работайте с вашей текущей веткой как хотите.
Что значит «будет заменен нашим патчем»? Вероятно, у вас неверное понимание того, как гит работает.
Во-первых, rebase работает с любыми ветками. Всё зависит только от ваших потребностей и фантазии.
Во-вторых, гит не работает «файлами», и потому ничего не будет «замещаться». Гит работает чендж-сетами — фактически, это набор изменений в наборе файлов. Т.е. такой себе монолитный, неразрывный патч, обо всех изменениях в конкретном коммите.
Для освежения памяти (вы же прочитали man по rebase, верно?...) — позволю себе утащить оттуда картинку:
Когда делается rebase, то гит последовательно для всех указанных вами коммитов (т.е. фактически — чендж-сетов) — в данном случае: A, B, C — делает cherry-pick на временную ветку (назовём её topic'), и когда процесс закончится — ваша ветка удаляется, а временная переименовывается в используемое ранее имя.
По сути своей, cherry-pick — это тот же merge, но не со всей веткой от указанного коммита, только с одним, явно указанным чендж-сетом. Как и при любом другом слиянии, тут могут возникнуть конфликты. И если вы меняли file1, а кто-то в master'е менял этот же файл в тех же строках — конфликт будет, как и всегда в таких случаях. Если же чендж-сет в master'е для коммита с изменениями в file1 не пересекается с вашим чендж-сетом, то слияние будет беспроблемным.
А по поводу безобидности… Ну вы же слияния делаете, и опасными их не считаете? Так тут по сути то же самое. Хотя как и везде — обязательно найдётся кто-то, кто оправдает поговорку про «и #$% разобъёт, и руки порежет» :)
Надеюсь, это прольёт свет на ваши вопросы.
Во-первых, rebase работает с любыми ветками. Всё зависит только от ваших потребностей и фантазии.
Во-вторых, гит не работает «файлами», и потому ничего не будет «замещаться». Гит работает чендж-сетами — фактически, это набор изменений в наборе файлов. Т.е. такой себе монолитный, неразрывный патч, обо всех изменениях в конкретном коммите.
Для освежения памяти (вы же прочитали man по rebase, верно?...) — позволю себе утащить оттуда картинку:
# было
A---B---C topic
/
D---E---F---G master
# любая из этих команд приведёт к ....
git rebase master
git rebase master topic
# стало
A'--B'--C' topic
/
D---E---F---G master
Когда делается rebase, то гит последовательно для всех указанных вами коммитов (т.е. фактически — чендж-сетов) — в данном случае: A, B, C — делает cherry-pick на временную ветку (назовём её topic'), и когда процесс закончится — ваша ветка удаляется, а временная переименовывается в используемое ранее имя.
По сути своей, cherry-pick — это тот же merge, но не со всей веткой от указанного коммита, только с одним, явно указанным чендж-сетом. Как и при любом другом слиянии, тут могут возникнуть конфликты. И если вы меняли file1, а кто-то в master'е менял этот же файл в тех же строках — конфликт будет, как и всегда в таких случаях. Если же чендж-сет в master'е для коммита с изменениями в file1 не пересекается с вашим чендж-сетом, то слияние будет беспроблемным.
А по поводу безобидности… Ну вы же слияния делаете, и опасными их не считаете? Так тут по сути то же самое. Хотя как и везде — обязательно найдётся кто-то, кто оправдает поговорку про «и #$% разобъёт, и руки порежет» :)
Надеюсь, это прольёт свет на ваши вопросы.
Можно сделать git log branch1..branch2 — тогда будут показаны только те коммиты ветки branch2, которые не присутствуют в ветке branch1.
Но, вроде бы, ничего не покажется если в branch2 только-что вливали branch1.
> Я плохо знаю устройство git'а изнутри…
Символично…
Ваш ник какбэ намекает ;)
Символично…
Ваш ник какбэ намекает ;)
git merge options:
-m Set the commit message to be used for the merge commit (in case one is created)
Или это не то?
-m Set the commit message to be used for the merge commit (in case one is created)
Или это не то?
Здравая вещь. Мне всегда было странно почему, merge не является причиной для commit. Теперь все по-уму.
> merge не является причиной для commit
Это как?!?! Ещё как является! Просто раньше сообщение к коммиту подставлялось уже готовое, и редактор для него не вызывался — потому коммит проходил тихо и незаметно. Чтоб поменять это сообщение (что за всё время работы с гитом мне понадобилось сделать ровно один раз) — нужно было сразу после
> Здравая вещь.
Кому как. Меня текущее поведение устраивало в 99.999% случаев, и этот (теперь) обязательный вызов редактора для меня просто лишняя трата времени. Так что надо будет сконфигурить алиас в ~/.gitconfig для вызова
Это как?!?! Ещё как является! Просто раньше сообщение к коммиту подставлялось уже готовое, и редактор для него не вызывался — потому коммит проходил тихо и незаметно. Чтоб поменять это сообщение (что за всё время работы с гитом мне понадобилось сделать ровно один раз) — нужно было сразу после
git merge
явно делать git commit --amend
, и менять сообщение вручную. Теперь просто поменяли поведение по умолчанию, и git merge
будет подставлять точно такое же сообщение, как и раньше, и сразу, до фиксации коммита, будет вызывать редактор. Вам решать — менять его или нет. И только после этого будет зафиксирован коммит.> Здравая вещь.
Кому как. Меня текущее поведение устраивало в 99.999% случаев, и этот (теперь) обязательный вызов редактора для меня просто лишняя трата времени. Так что надо будет сконфигурить алиас в ~/.gitconfig для вызова
merge --no-edit
.Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Изменение поведения git merge в релизе 1.7.10