1 Востаннє редагувалося wander (06.10.2020 23:59:35)

Тема: Яким ґвалтуванням ґіту тут займалися?

Після кількох днів відпустки заходжу подивитись, що там накомітали мої тімейти й бачу ось таке:

          ( a1 ) <- ( a2 ) <- ( a1' ) <- ( a2' ) <- ( a3 ) <- ( a4 ) [test branch]
             |
( m1 ) <- ( m2 ) [master branch]

Всі коміти без позначки ' — звичайні коміти.
Коміти a1' і a2' - це ті ж коміти, що й a1, a2, але з іншими SHA.
Як думаєте, що тут сталося? І, як це виправити? )
Всі коміти з гілки test були запушені на ремоут.

Прихований текст

Я розібрався, що сталося, але, як це виправити ще ні ...

2

Re: Яким ґвалтуванням ґіту тут займалися?

Хтось редагував коміти.

Подякували: Yola1

3

Re: Яким ґвалтуванням ґіту тут займалися?

Ні, все трохи банальніше

4

Re: Яким ґвалтуванням ґіту тут займалися?

Так, схоже на форумі відповіді не дочекався б :)
Гаразд, розкажу, що сталося, чому так сталося й чому так краще не робити.
А, якщо хтось попаде в таку ж халепу, то буде міні гайд, як це виправити.

Отже, коміти-копії появилися в нас у наслідок git rebase. Ідея rebase полягає в тому, щоби перебазувати дані для вашої гілки, але лише якщо ви ще не пушили нічого, щоби відтворити ваші локальні коміти. Як тільки ви пушнули (і працюєте в команді), вам не треба перебазовувати (rebase) гілку поверх майстра, оскільки вона переписує свій SHA1, змушуючи вас примусово пушити новий стан гілки (git push -f). Відповідно, якщо ви цього не знаєте, то роблячи git rebase для пушнутої гілки, перетворить її у стан diverged, після чого git запропонує зробити спочатку git pull, а потім git push замість force push, чого робити категорично не можна. В таких випадках бажано зробити git merge master у вашу гілку.

І от, якщо ви послухались поради git'a та зробили pull + push, то отримаєте такі от небажані коміти-копії. Як це можна виправити? Ймовірно, це можна зробити по-різному, але я робив так:

0. Переконайтесь, що знаходитесь на потрібній гілці, інакше зробіть $ git checkout <потрібна гілка>
1. Робимо $ git reset -hard <на коміт перед тим, як ви робили rebase>
2. Робимо $ git merge master у вашу гілку (не навпаки)
3. Чері-пікаємо необхідні коміти, які ні в чому не винні та мають залишитися $ git cherry-pick <коміт>
4. Ну і наостанок, робимо $ git push -f
Подякували: leofun01, dekameron, dot3

5

Re: Яким ґвалтуванням ґіту тут займалися?

Власне Vo_Vik дав вам відповідь. Редагувати коміти це і -f.

6 Востаннє редагувалося frz (Вчора 22:26:43)

Re: Яким ґвалтуванням ґіту тут займалися?

Велика фіча, 12 штук PR в стаку, де кожен ґіт бранч залежить від попереднього, один за одним. Рев'ювер просить змінити перший. Фіксиш, робиш push with lease.

Всі наступні PR тепер базуються на коді ДО цієї зміни. Треба зробити rebase в #2, потім #3-й ... #12. Конфлікти вилізають в кожному, бо є спільні файли в які вносилися зміни в різних PR.

Чим більше PR в ланцюжку, тим дорожче мейнтейнити. Ефект доміно, тільки з merge конфліктами.

Складність = O(кількість PR × конфліктні комміти).



Як виглядає процес:

# фікс в одному з перших PR
git checkout pr1
# фікси
git commit ...
git push --force-with-lease

# rebase наступний PR
git checkout pr2
git fetch origin
git rebase origin/pr1
# резолвимо конфлікти
git rebase --continue
git push --force-with-lease

# rebase наступний PR
git checkout pr3
git rebase origin/pr2
# резолвимо конфлікти
git rebase --continue
git push --force-with-lease

...

(і так 12 разів)

Типова послідовність коли щось потрібно інвестіґейтити:

git status
git diff --name-only --diff-filter=U

git checkout --ours <file> # ours це у найкращому сценарії - найлегший фікс
git add <file>

git rebase --continue # це для кожного коміту в PR, поки не залишиться конфліктів


Валідація перед тим як пушити:

python3 -m compileall path1/src
python3 -m compileall path2/tests/unit
pytest path2/tests/unit -q


Ментальна модель:

зміна в PR1
  ↓
rebase PR2
  ↓
rebase PR3
  ↓
rebase PR4
  ↓
...
rebase PR12
force-push кожен бранч.


(процес дуже на любителя, особисто не раджу).


----

Висновок: просити рев'ювати із change request лише в останньому PR.

Написано на підставі гіркого досвіду.