Гілки та хірургія

Стековані гілки

Стек — це ланцюжок гілок, де кожна будується на тій, що під нею: main → api → ui. Переглянути три невеликі PR приємніше, ніж один величезний.

Стек гілок

Gitcito малює його як маршрут: згори стартова гілка, нижче по одній зупинці на рівень. PR кожної зупинки націлений на зупинку вище, а перша приземляється на стартову гілку. Зупинка показує власні коміти, чи потрібен їй restack і — після надсилання — номер PR.

Редагування маршруту

Нічого не виконується, доки ви не натиснете «Застосувати». Вибрати гілку, пересунути зупинку, прибрати її з маршруту — усе це редагує список на екрані. Справжня операція перебазовує гілки й перемикається на них, а цього не має робити цікавий клік. Коли маршрут читається правильно, Застосувати маршрут виконує його одним скасовним кроком; Скасувати повертає рисунок до того, що каже репозиторій.

Маршрут намальовано в порядку злиття: верхня гілка вливається в ту, що нижче, аж до гілки, на яку приземляється стек.

Елемент Що робить
Поле Старт Куди приземляється стек. Змініть — і весь ланцюг перечепиться на нову гілку та переграється.
Поле зупинки Змінює, яка гілка займає це місце. Гілка, що зійшла з маршруту, лише відв'язується, її не видаляють.
↑ / ↓ Пересуває зупинку на одну позицію.
✕ Знімає зупинку з маршруту; сусіди змикаються.
Додати зупинку Виберіть гілку, яку вже маєте — вона стане на вершину маршруту, — або введіть ще неіснуючу назву: гілку буде створено на вершині останньої зупинки й перемкнено на неї.
Кнопка зі стрілкою Перемикає на цю зупинку.

Усі поля мають підказки під час набору: друкуйте, щоб відфільтрувати, ↑/↓ та Enter, щоб обрати, а набране поза списком теж зараховується — тож віддалене посилання на кшталт origin/main годиться як стартова гілка.

Під капотом усі ці правки — та сама операція: маршрут цілком, відданий за раз. Тому один жест — одне скасування (⌘Z), а не слід із наполовину застосованих зв'язків.

Скільки коштує правка маршруту

Усе, що змінює порядок — обмін, зсув, інший старт, — переграє ланцюг: власні коміти кожної зупинки перебазовуються на нову основу. Тож може статися конфлікт, так само як під час restack. Дві зупинки, що чіпають ті самі рядки, не поміняються місцями без людини, і тоді нічого не стається: уся правка відкочується — вершини, батьківські зв'язки й незавершений rebase, — а Gitcito називає дві зупинки, що зіштовхнулися. Зачеплений список не має кидати вас посеред rebase.

Restack — друга половина угоди: це rebase, про який ви попросили прямо, тож він спиняється на конфлікті й віддає вигляд розв'язання — а це і є спосіб дістати перестановку, в якій Gitcito відмовив: розв'яжіть там, потім рухайте зупинку.

Скасування переграє попередній маршрут. Воно не воскрешає старі коміти: нові — та сама робота з іншими батьками.

Надіслати все

Надіслати все надсилає кожен рівень із --force-with-lease і на цьому спиняється — це gh stack push, який нічого не відкриває. Надіслати стек як PR робить той самий push, а далі роботу з PR; беріть Надіслати все, коли гілки потрібні на віддаленому, а до рецензії ще далеко.

Надішліть стек як зв’язані PR

Подати спершу питає: скільки pull request’ів відкриє, скільки перенацілить, на якому віддаленому репозиторії та по рядку гілка → база на кожен — відкриття PR публічне й скасовується важко. Розділ навігації, вписаний у кожен опис, і робить ланцюг видимим на GitHub, який про стеки не знає нічого.

Надсилання відбувається на окремому екрані: спершу план, потім поступ покроково, а наприкінці — посилання на кожен pull request і на сам стек.

Надсилання стека

Надіслати стек як PR робить одним кліком те, за що інструменти для стеків беруть гроші:

  1. Пушить кожен рівень із --force-with-lease (свіжі гілки це терплять, а перескладеним воно необхідне).
  2. Відкриває PR для кожного рівня, де його немає — кожен на основі батьківської гілки, а не main, тож кожне рев’ю показує лише власні коміти. Заголовок і опис беруться з комітів самого рівня.
  3. Перенацілює наявні PR, чия база з’їхала.
  4. Записує в тіло кожного PR розділ навігації по стеку, щоб рев’юер на будь-якому рівні бачив увесь ланцюжок і місце цього PR у ньому.

Дія ідемпотентна: натискайте її після кожного перескладання, нового рівня чи злитого PR — вона сходиться: ніщо не дублюється, зачіпається лише те, що з’їхало.

Коли нижній PR злито, та сама кнопка прибирає за ним: нащадок злитого рівня перечіплюється на основну гілку, рівень прибирається зі стеку, його локальна гілка видаляється (це безпечно — основна гілка доказово її містить), ланцюжок перескладається, а всі решта PR перенацілюються. Зливайте знизу вгору, натискайте «Надіслати», повторюйте.

На GitHub це ще й справжній стек

Зчеплені бази розуміє будь-який хостинг, а на GitLab, Bitbucket і Azure DevOps це все, що є. У GitHub більше: від виходу превʼю stacked pull requests стек став обʼєктом на сервері. Щойно pull requestʼи створено, Gitcito реєструє їх як стек — знизу вгору, — і ви отримуєте карту стека в інтерфейсі PR, каскадний rebase на боці сервера та merge верхнього PR, який приземляє всі рівні під ним.

Якщо репозиторій не в цьому превʼю або токен не вміє керувати стеками, виклик тихо пропускається: ланцюг і його розділ навігації тримаються самі, так само як на інших хостингах.

Перескладання

Коли змінюється нижня гілка — ви врахували зауваження рев’ю в api — усі гілки над нею тепер побудовані на неправильній основі. Перескласти каскадом робить ребейз усього ланцюжка через rebase --onto, тож переписування батьківської гілки не дублює коміти в її нащадках. Після перескладання натисніть Надіслати ще раз: переписані рівні буде запушено примусово, і PR оновляться на місці.

Обмеження

  • Надсилання поки працює лише з GitHub (створення працює на всіх чотирьох хостах, але перенацілення й оновлення тіла потребують API GitHub).
  • Прибирання після злиття низу бачить звичайні злиття і злиття через ребейз за походженням, а squash-злиття — запитуючи GitHub, чи приземлився pull-реквест гілки; тож із токеном GitHub прибирається будь-який стиль злиття. На інших хостах або без токена рівень, злитий через squash, усе ще доведеться прибрати зі стеку вручну. І спершу зробіть fetch — перевірка походження читає основну гілку станом на ваш останній fetch.
  • Розділ стеку в тілі PR підтримується між прихованими маркерами — ваш власний опис над ним зберігається.
  • Перевпорядкування та зміна стовбура переписують історію на кожному зачепленому рівні. Гілки ваші, і ненадіслані рівні нічого не коштують, але рівень, що вже на рецензії, отримає force-push під час наступного надсилання.
  • Рівень зсувається на одну позицію за раз. Два обміни — це два rebase, і зупинка на півдорозі лишається читабельним станом; перетягування одразу на три позиції — ні.
  • Зупинка перебазовується, тож гілка, на яку приземляється стек, ніколи не є водночас зупинкою — як і захищена гілка (main і master, поки ви не змінили список). І те, і те відхиляється, а не переписує мовчки спільну історію.
  • Перш ніж щось відкривати, надсилання питає віддалений репозиторій, які гілки справді дійшли, і називає ті, що ні. На відсутній head GitHub відповідає сухим «Validation Failed», з якого ніхто нічого не має. Гілку, на яку приземляється стек, теж перевіряють: якщо вона лише локальна, надсилання запропонує надіслати її й продовжити.

Де живуть зв’язки

Зв’язки з батьківськими гілками зберігаються в конфігурації git, тож вони подорожують разом із репозиторієм і переживають повторне клонування. Ніщо не живе в жодному сервісі.

Дивіться також: Інтерактивний ребейз · Хостинг та pull-реквести

Покращити цей переклад на GitHub