Как стать автором
Обновить

Комментарии 49

Саш, я помню, что раздел про history simplification в мане про git-log был ещё лет 5 назад… Впрочем, может быть, ты прав, что он был только в rev-list.


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


Ещё в целом прикольные подводные камни возникают, когда в прямо merge-коммите что-то дополнительно добавляют или убирают, а не просто разрешают конфликты. В таких случаях раньше git show -p для такого коммита ничего не показывал, а git log <filename> по-моему не показывает merge-коммиты по умолчанию :).

Ну про полгода явно ошибка.
web.archive.org/web/20200103050848/https://git-scm.com/docs/git-log

В январе этого года (почти год назад) этот раздел уже был. Более старое затрудняюсь посмотреть, вебархив сбоит сильно. Болеет видимо :-(
Спасибо, я действительно ошибся. Я точно помню что не обратил внимание на этот раздел, когда смотрел документацию в попытке разобраться, что происходит. Могу только предположить, что искал в документации какие-то комментарии к флагу --follow. А на раздел наткнулся уже после того, как залез в код.

Намного позже, когда писал статью, решил что не просто не заметил этого куска, а его не было. Конкретно из-за этого коммита: в нем в документацию git-log добавилось
include::rev-list-description.txt[]
а вот
include::rev-list-options.txt[]
уже там было (похоже где-то лет 10 как). Простите, немного человеческой невнимательности :)
Ответил про history simplification в ветке, похоже что ты прав.

Искренне считаю, что самый крутой вариант — это когда в merge добавляют что-нибудь, даже если никакого конфликта не было :)

Спасибо за интересную историю.

Да, присоединяюсь. Понравилась манера подачи, читается как детективчик :)
С удовольствием провел время с пользой, спасибо.

О, это может никак не помочь отвлечь мозг от недоисследованной проблемы. Такие цепляют и хочется понять "да как оно так то?! и как избежать/починить в будущем?"(иногда добавляется "так, а как оно раньше то работать вообще умудрялось!?").


И порой проще действительно вот как тут закопаться и докопаться — и пойти дальше по таскам.

Вообще, находить причину проблемы обычно помогает ее исправить и не допустить в будущем, что обычно хорошо, как минимум для компании.

Обычно да, но иногда это вступает в противоречие с сиюминутными приоритетами. Например при дедлайне перед выставкой какой или выпуском версии. И вот тут нежелание мозга отпустить на время проблему может мешать.

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

Согласен.

хехе. после этих rebase-ов еще и не такие приколы поиметь можно.
c merge-ами хотя бы можно разобраться что к чему было, кто, когда и зачем

Как раз таки при merge такие проблемы чаще всего и остаются незаметными, т.к. большая пачка изменений conflict resolution идёт в итоговый merge commit. При rebase удаление кода из мастера было бы частью непосредственно коммита, который добавляет новую версию кода — и сразу привлекало бы внимание как при ревью кода, так и при просмотре истории.


А вообще лучше всего использовать rebase и merge одновременно (с пустыми merge commit), и получать преимущества обоих вариантов!

Программист удалил конфликтный код при слиянии. По-моему, все логично. Коммит есть, а кода нет.
Ну, только merge коммита в выводе git log {filename} в таком случае тоже не будет видно. Поэтому коммит есть, кода нет, merge коммита тоже нет :)

Понять не могу: как получится этот коммит afea493a?
Если я мержу changekiller в master, то появляется конфликт и 2 варианта:


  • решаем конфликт в пользу changekiller — мерж-коммит не пустой (видно изменение)
  • решаем конфликт в пользу master — мерж-коммит пустой, но и в master ожидаемое 3, а не 4

Буду признателен если кто-нибудь распишет последовательность действий.

Я слепой… Использовался git merge -s ours

В обсуждении уже восстановили минимальную последовательность действий. Читайте до конца.

Причём я тоже натыкался на подобное. Происходит от непонимания работы git со стороны разработчика. Если я правильно понял, то механизм примерно такой:


  • Разработчик ответвляется от master в feature ветку. Пока всё ОК.
  • Фигачит код, коммитит, пушит к себе в ветку. Пока всё почти ОК, кроме того, что если приходится атомарные изменения делать несколько дней, то это "симптомчик" про сложность кода.
  • master (логично) убегает вперёд. Разработчик подмёрживает к себе изменения master. А там конфликт, чтобы не греть голову чувак оставил только свои изменения. Вот это и есть основная засада (ниже перечислю что не так).
  • Потом еще что-то коммитит в свою ветку.
  • Потом замержил с master (уже как будто "без конфликтов").

Что не так:


  1. Неаккуратный мерж к себе.
  2. По хорошему всю ветку надо либо аккуратно ребейзить в хвост мастера, либо делать squash своих изменений в один коммит (если он атомарен). Ключевое слово "аккуратно". Заодно история станет прозрачнее.
  3. В гите в истории нет понятия "коммит был в такой-то ветке". Обе сливающиеся ветки (или все N веток) равноправны. И поэтому делая мерж от master к себе каждый разработчик отвечает за этот мержевый коммит. Поэтому публикуя пулл/мерж реквест разработчик отвечает за каждый коммит, добавляемый в основной граф. В том числе и за такие "технические" мержи. Поэтому пулл/мерж реквест должен по-хорошему содержать коммиты от максимально свежего, не содержать лишних ветвлений и мержей — это позволит сильно экономить мыслетопливо при чтении истории.

Какой еще rebase после push?

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

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

Тогда это уже не является веткой, с которой работает один человек. Если этот «кто-то» самолично принял такое решение, то это сугубо его проблемы. Если же данный факт согласован со мной, то и я ветку не считаю только лишь своей.

Если таков ваш корпоративный workflow, ничего не могу возразить, но в общем случае изменение истории на сервере не поощряется.

Вопрос можно? А не является ли эта история следствием каких-то организационных проблем?

Каких например?

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

Что разработчик сделал merge, a не pull/merge request, который, если не ошибаюсь, был бы отклонен как раз из-за конфликта. А дальше, см. stackoverflow.

Так у нас такая же ситуация как по вашей ссылке на stackoverflow: у разработчика есть ветка с его кодом, которая конфликтует с мастером. Разработчик подтягивает мастер к себе в ветку, разрешая конфликт «в пользу своих изменений». Потом уже его ветка попадает в мастер, и уже без конфликтов, а мы получаем всю эту историю с потерянным коммитом.

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

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

В вашем тестовом репозитории я этого не вижу. Ветка changekiller мержится в master.

В тестовом репозитории я пытался сделать минимум всего, просто чтобы показать проблему: коммита действительно не видно. Показалось что было бы приятно иметь возможность «пощупать» самому то, о чем идет рассказ :)

Немного напоминает совет не пользоваться многократным undo и redo в редакторе кода, когда результат может не всегда совпадать с исходным.

Можно подробнее, никогда с таким не сталкивался?
Хорошая история, спасибо

Уважаемый автор, я скачал ваш репозиторий, посмотрел на него PyCharm'ом и, да, в Log'е не не сразу очевидно, что произошло (надо всматриваться), а вот если попросить Git history файла test.php, то все видно мгновенно — то, что вы при разрешении merge conflict не приняли изменений в changekiller, в отличие от ситуации, описанной в статье.


P.S. И там еще много лишнего видно типа ветки interesting_changes — удалить надо?

Не обращал внимание, но вы правы, в IDE JetBrains на тестовом репозитории все отлично видно. К сожалению, сам привык пользоваться в Git в консоли :(

P.s. Лишнюю ветку удалил, спасибо!
Вот я тоже не понимал в чем собственно проблемма — посмотрел на граф, историю — и всё ясно, пока до меня не дошло, что автор только командной строкой пользуется.

Интересная проблема


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

НЛО прилетело и опубликовало эту надпись здесь

См. тестовый репозиторий и мою дискуссию с автором статьи выше. Т.е. в конце концов. таки (другой) программист, который делал рефакторинг, смержил свою ветку обратно в мастер. Иначе, как бы еще могли потеряться исправления в master'е?

НЛО прилетело и опубликовало эту надпись здесь

Ну, судя по статье и тестовому репозиторию первого мержа из мастера в ветку не было… Лишь в процессе обсуждения выяснилось, что автор посчитал его несущественным для объяснения ситуации.


И да, я проверил, что если в ветке файл правится, потом мерж из мастера с конфликтом, криво разрешенным в свою пользу, то последующий мерж из ветки в мастер — уже без формального конфликта, но приводящий к regresson ошибке.


Как причину ошибки искать, это уже второй вопрос (с простым ответом, или консольные команды лучше знать, или GUI пользоваться), а вот как поймать и не допустить? Только если тестами, так ведь и их можно в ветке кривым мержем "откатить".

Когда только начинал пользоваться GIT, спросил коллег чем он лучше моего старого подхода, когда каждый день создавал архив с названием в виде даты и заливал в облако. Мне объяснили, что будет видна история изменений, что ничего не потеряется и т.д. Через пару дней я сделал что то не так и приличный кусок правок исчез. Те же коллеги сказали, ну так бывает, в винде работают некоторые вещи не очень в гите. Мой текущий подход, это, конечно же, GIT, но привычку сохранять в архивы я оставил, на всякий случай.
НЛО прилетело и опубликовало эту надпись здесь
Я понимаю что работает достаточно хорошо, но инструмент сложный, и доверять ему на 100% не стоит как и любому другому сложному софту. Должен быть и запасной вариант.
Хорошо написано, есть над чем подумать, спасибо
Зарегистрируйтесь на Хабре, чтобы оставить комментарий