git rebase

katrin2201

Есть ветка upstream, есть ветка master.
В ветку мастер я пишу свои хаки. В ветку upstream пуллю новые коммиты из оригинального дерева и периодически мерджу свой master с этим upstream'ом. В итоге мои коммиты идут вперемешку с коммитами из апстрима. Изначально делать rebase я не мог, потому что master виден не только мне.
Теперь я хочу сделать экспериментальную ветку, и чтобы там мои коммиты "всплыли" над коммитами из апстрима, то есть все мои коммиты были в конце. Я наивно полагал, что git rebase upstream сделает мне это. Он вроде бы и пытается, только у него как-то странно получается, потому что на пустом месте прут merge conflict'ы.
Один из стандартных кейсов - это когда в очередном сфейлившемся патче все, что я делаю - это создаю новый файл. И в патче это явно видно, что на стороне a - /dev/null, на стороне b - мой новый файл. При этом git считает, что это о ужас конфликт, и в самом конфликтном файле очень похоже что показывает мне сравнение между моим master до ребейза и файлом после текущего патча. Файл точно есть только в моих коммитах, в upstream такого файла нет. Это что-то очень странное, что наводит меня на мысль, что я делаю что-то не то.
Если поискать в гугле, то там люди жалуются на то, что ребейз заставляет их редуить мерджи, то есть заново резолвить те конфликты, которые резолвили при мерджах.
Но блин, у меня то он просит резолвить те конфликты, которых никогда не было! А заредуить те конфликты, которые делались - я готов, их там немного.
Может кто-то нателепатит, ЧЯДНТ?

kill-still

Выкачай все коммиты из своей ветки master в патч, переключись на upstream да накати туда патч. Делов-то. :)

katrin2201

Смешно, но ради собирания патча я это все и затеял.
Я, собственно, и хотел всплыть все свои коммиты, чтобы не черри-пикать руками список коммитов, которые надо унести в патч, а тупо выбрать последние коммиты в ветке.
С проблемой я в общем-то можно сказать справился, таки померджив все, что он мне предлагал руками. Но непонимание осталось в двух пунктах:
1. Какого черта мердж конфликты перли там, где раньше их не было, да и не могло бы быть?
2. Какого черта в конфликтных файлах он делал 3-way merge, где base был правильный (до патча a-side правильный (после патча а b-side какой-то неожиданный - HEAD исходной ветки со всеми коммитами, моими и ихними, которую я собственно и ребейзил?
Второй пункт я еще наверное как-то могу понять, оно типа мне показывало финальный результат, как оно в итоге было смерджено и могу смириться, потому что в общем-то действительно неочевидно, с каким ченджем диффать.
Но вот первый пункт никак понять не могу... Каким макаром можно неудачно накатить патч, который создает _новый_ файл? Может быть оно пытается быть слишком умным, подсматривает в HEAD, видя что там файл уже есть, но не такой, и ему сносит мозг? Но это какая-то чересчур странная логика. Может, ее можно отключить?
В общем, если кому-то интересно, я могу, пожалуй, скрафтить набор команд, который будет демонстрировать это непонятное мне поведение.

vall

Я наивно полагал, что git rebase upstream сделает мне это.
неа, ты сам себе злобный буратино навязал узлов. ты делал git rebase --interactive? мне кажется git cherry-pick master...upstream тут был-бы более удобен.

katrin2201

неа, ты сам себе злобный буратино навязал узлов. ты делал git rebase --interactive? мне кажется git cherry-pick master...upstream тут был-бы более удобен.
Печалька =( А почему? Ну наворотил я узлов, ну и что? Ребейз по дефолту пропускает же мердж коммиты.
rebase был без --interactive. Есть какая-то разница, кроме того что он после каждого коммита будет стопаться?
cherry-pick master..upstream - да, возможно ты прав...

vall

cherry-pick master..upstream - да, возможно ты прав...
master...upstream три точки. это важно. наверно.
интерактивно ты можешь выделить явно то что нужно тащить.
чтож флокал так тормозит. это у меня одного?

istran

По-моему твоя ошибка заключается в том, что ты мержил свой master c upstream, вместо того чтобы rebase-ить master поверх upstream.
Чтобы все исправить, можно например создать новый branch, и перенести туда все свои коммиты:

git checkout upstream
git checkout -b master2
git log --author=<YOUR_NAME> --reverse --format=format:%H master | xargs git cherry-pick
git -M master #ACHTUNG! оригинальный мастер будет удален

Теперь можно использовать правильный (IMHO) workflow:

git checkout upstream
git pull
git checkout master
git rebase upstream

Теперь все твои коммиты находятся в истории выше коммитов из upstream.
 UPD: извиняюсь, не прочитал, что нельзя было делать rebase.

katrin2201

чтож флокал так тормозит. это у меня одного?
Вроде да, у меня вчера не тупило. За совет спасибо.

katrin2201

Ребейз всей ветки не мог делать, ага.
За дао с cherry-pick спасибо

istran

У меня ошибка была, надо добавить опцию --reverse к git log, чтобы коммиты накатывались в правильном порядке, а не в обратном. Сейчас поправил.
Оставить комментарий
Имя или ник:
Комментарий: