Khi làm việc với stacked pull requests trên GitHub, đôi khi bạn cần thay đổi cấu trúc của stack - sắp xếp lại các nhánh, kết hợp chúng, hoặc đổi tên. GitHub CLI extension gh stack cung cấp công cụ mạnh mẽ để xử lý việc này một cách dễ dàng.
Vấn đề#
Khi phát triển tính năng theo kiểu stacked PRs, bạn thường gặp các tình huống:
- Cần di chuyển một nhánh lên vị trí cao hơn hoặc thấp hơn trong stack
- Muốn gộp hai nhánh lại với nhau
- Cần xóa một nhánh khỏi stack nhưng vẫn giữ lại PR
- Muốn chèn một nhánh mới vào giữa stack
- Cần đổi tên nhánh để phản ánh đúng nội dung
Thay vì thực hiện thủ công với git rebase và force push phức tạp, gh stack cung cấp các lệnh chuyên biệt.
Giải pháp#
GitHub CLI cung cấp hai cách chính để tái cấu trúc stack:
1. Sử dụng gh stack modify (Khuyên dùng)#
Lệnh này mở giao diện terminal UI tương tác cho phép bạn thực hiện các thay đổi cấu trúc và áp dụng tất cả cùng lúc.
gh stack modifybashGiao diện TUI hỗ trợ các phím tắt:
| Phím | Hành động | Mô tả |
|---|---|---|
x | Drop | Xóa nhánh và commit khỏi stack |
d | Fold down | Gộp nhánh vào nhánh bên dưới (hướng về trunk) |
u | Fold up | Gộp nhánh vào nhánh bên trên (xa trunk) |
i | Insert below | Chèn nhánh mới trống bên dưới (hướng về trunk) |
I | Insert above | Chèn nhánh mới trống bên trên (xa trunk) |
Shift+↓ | Move down | Di chuyển nhánh xuống (hướng về trunk) |
Shift+↑ | Move up | Di chuyển nhánh lên (xa trunk) |
r | Rename | Đổi tên nhánh |
z | Undo | Hoàn tác hành động đã staged |
Ctrl+S | Apply | Áp dụng tất cả thay đổi |
2. Sử dụng gh stack unstack + gh stack init#
Cách tiếp cận thủ công hơn nhưng linh hoạt cho các thay đổi phức tạp:
# 1. Xóa stack hiện tại
gh stack unstack
# 2. Thực hiện thay đổi cấu trúc thủ công
git branch -m api-routes api-endpoints
git branch -d feature-removed
# 3. Tạo lại stack với cấu trúc mới
gh stack init db-migrations api-endpoints frontendbashQuy trình tái cấu trúc#
Dưới đây là quy trình tái cấu trúc một stack:
flowchart TD
A[Stack hiện tại] --> B{Phương pháp?}
B -->|Tương tác| C[gh stack modify]
B -->|Thủ công| D[gh stack unstack]
C --> E[Mở TUI]
E --> F[Chọn hành động]
F --> G[Stage thay đổi]
G --> H{Đã xong?}
H -->|Chưa| F
H -->|Xong| I[Ctrl+S Apply]
D --> J[Thay đổi thủ công]
J --> K[git branch -m/-d]
K --> L[gh stack init]
I --> M[Cascading rebase]
L --> M
M --> N[gh stack push]
N --> O[Stack đã tái cấu trúc]
Ví dụ thực tế#
Ví dụ 1: Di chuyển nhánh lên vị trí cao hơn#
Giả sử bạn có stack từ dưới lên trên:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes]
C --> D[frontend]
D --> E[testing]
Bạn muốn di chuyển testing lên trên api-routes:
gh stack modify
# Sử dụng Shift+↑ để di chuyển testing lên
# Ctrl+S để áp dụngbashKết quả:
graph TD
A[main] --> B[db-migrations]
B --> C[testing]
C --> D[api-routes]
D --> E[frontend]
Ví dụ 2: Gộp hai nhánh#
Khi bạn nhận ra hai nhánh nên được gộp thành một:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes]
C --> D[api-validation]
D --> E[frontend]
Gộp api-validation vào api-routes:
gh stack modify
# Chọn api-validation, nhấn d (fold down)
# Ctrl+S để áp dụngbashKết quả:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes + validation]
C --> D[frontend]
Ví dụ 3: Chèn nhánh mới#
Khi bạn cần thêm một layer vào giữa stack:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes]
C --> D[frontend]
Chèn nhánh auth-middleware giữa api-routes và frontend:
gh stack modify
# Đặt con trỏ ở api-routes
# Nhấn I (insert above)
# Đặt tên cho nhánh mới
# Ctrl+S để áp dụngbashKết quả:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes]
C --> D[auth-middleware]
D --> E[frontend]
Quy trình cascading rebase#
Khi bạn áp dụng thay đổi với gh stack modify, quá trình sau sẽ diễn ra:
sequenceDiagram
participant User as Bạn
participant CLI as gh stack modify
participant Git as Git
participant Remote as GitHub Remote
User->>CLI: gh stack modify
User->>CLI: Stage thay đổi (di chuyển/gộp/chèn)
User->>CLI: Nhấn Ctrl-S để Apply
CLI->>Git: Đổi tên nhánh nếu cần
CLI->>Git: Chèn nhánh mới nếu cần
CLI->>Git: Cascading rebase
loop Qua từng nhánh
CLI->>Git: Rebase nhánh hiện tại lên nhánh dưới
Git-->>CLI: Rebase hoàn tất
end
CLI->>User: Thông báo thành công
User->>CLI: gh stack push
CLI->>Remote: Force push với `\-\-force-with-lease`
Remote-->>CLI: Push thành công
CLI-->>User: Stack đã cập nhật trên GitHub
Lưu ý quan trọng#
[!WARNING]
- Không thể sửa đổi nhánh từ PR đã merged
- Các thay đổi cấu trúc (drop, fold, insert, rename) không thể trộn trong cùng một session
- Luôn sử dụng
gh stack pushvới--force-with-leaseđể an toàn- Backup branch quan trọng trước khi tái cấu trúc lớn
Best practices#
- Kiểm tra stack hiện tại: Luôn chạy
gh stack viewtrước khi thay đổi - Sử dụng TUI:
gh stack modifyan toàn hơn vì preview thay đổi trước khi apply - Test cục bộ: Đảm bảo rebase thành công trước khi push
- Communicate: Thông báo team về thay đổi cấu trúc stack lớn
- Backup: Đánh tag hoặc branch backup cho stack quan trọng