# Git rebase -i


## Git rebase


> Khuyến mãi link học git game [Link](https://learngitbranching.js.org/)

Git rebase để làm với mục đích làm cho toàn bộ commit của source code theo thứ tự.
Git rebase cần phải làm với nguyên tắc là 
1. Trước khi tách nhánh thì phải dùng lệnh checkout master và pull toàn bộ master mới nhất thường với lệnh `git checkout master && git pull`
1. Sau đó thì từ source code mới nhất của master sẽ làm lệnh tạo nhánh và checkout nhánh mới luôn `git checkout -b <new_branch> `
1. Sau đó vào trong nhánh mới tạo làm việc và commit code thoải mái.

1. Để tránh mất code trên máy tính thì phải push code lên git. Và Trước khi push code thì phải nhớ làm động tác là
- Commit trên branch đang làm việc
- sử dụng lệnh `git checkout master && git pull` để kéo code mới nhất về lại
- ***CHECKOUT*** lại branch đang làm việc và sau đó dùng lệnh `git rebase master` để ***Gắn toàn bộ commit của branch đang làm lên trước commit mới nhất của master***
- Sau đó dùng lệnh đẩy branch đang làm lên git `git push -f origin <tên_branch>` 
> Lưu ý: Khi dùng lệnh rebase từ feature branch qua master thì có một vấn đề nảy sinh là có thể có nhiều commit từ feature branch không khác nhau nhiều code cho mỗi lần thay đổi và do đó thì ta nên **gộp các commit lại với nhau** khi làm lệnh rebase

5. Sử dụng lệnh `git rebase -i master` để có thể mở ra một cửa sổ để ta có thể chỉnh sửa gộp, các commit với nhau lại trước khi rebase vào `master`. Cũng khá hay ho.

Xem hình để biết cụ thể hơn là nhánh `feature` tách ra từ nhánh `master` có cùng commit tới `master 1`
![git-flow](https://lh3.googleusercontent.com/32Uo_awtQ_JyqDJeak03Raa8ZQ_lGOgD6vHjfYaBaO6Zgv8a1P3z7bKv_t_4rZyTVNFnEGFhDWcLgw_yDYBhC_LnwfWirLu3Gg2Xa_sq8Py-Zj--xjDufqb7-lU4bSMxJrsO-ULSUg=w2400)
Hình tiếp theo. Nhánh `master` có thêm commit là `master 2` và `master 3` và đã push code lên nhánh `master`.
Checkout feature với lệnh `git checkout feature` và làm việc rồi commit là `branch 1` rồi `branch 2` và `branch 3`. <br>
Tại nhánh `feature ` tiếp lệnh `git checkout master && git pull` để checkout ra nhánh `master` và đồng thời `pull` toàn bộ commit mới nhất của nhánh master là tới `master 3` <br>
Sau đó `git checkout feature` để checkout lại nhánh `feature` và rồi sẽ dùng lệnh `git rebase master` để đưa toàn bộ commit mới nhất của branch `feature` lên trên đầu toàn bộ commit của nhánh `master`
![](https://lh3.googleusercontent.com/LB-Pl_JCUQDQVyHlJgo-cFtnd7nOSoiOBiG4DJUYoGUSyAc5r-usQ-0IiJDjWMbthyAVmFfPz8wDo_GpVQ-Jd2CX_2UsLiVlisEuFWwL3KdnNSdUzDOADhc8dkTUC-hPgFbRybAxyg=w2400)
Sau khi hoàn thành quá trình thì nhánh `feature` đã chứa toàn bộ commit của chính nó và những commit đó lại đứng trên toàn bộ commit của nhánh `master`
Kiểm tra thêm một lần nữa để thấy tình hình sau khi dùng lệnh `git rebase mater`
![sau-khi-git-rebase-master](https://lh3.googleusercontent.com/1Nc5HZm6FPn76Ra_TM5_JqsMhavKvXzYL-bRH2-uHlE8aUCKFd9cVABLvRHKBfxRkUst3F58dFarUoMwoveq7qnMstHQwfDIjzrQGBDEQQ1MNKg6ls6ZIhl5SSdQod0l4L-I8ORv_Q=w2400)
OK, mọi việc ở nhánh `feature` có thể quên đi vì nó đã ok rồi. Nhưng còn nhánh `master` thì sao? Rất đơn giản. Ta chỉ việc `git checkout master` và sau đó dùng lệnh `git merge feature` để merge nhánh `feature` vào `master` thôi và ta cũng chẳng cần lo lắng thiếu commit vì toàn bộ commit của master đã nằm **TRONG** và nằm **TRƯỚC** toàn bộ commit của nhánh `feature` và ta merge vào thì ngẫu nhiên `master` của ta đã **UP TO DATE** rồi còn gì.
![git-merge-feature](https://lh3.googleusercontent.com/loFbejPKcyobtuoYYY_3I3e3tgiwMRy0XphwftaWHiwC0k4Dm41cNSLX1NjOqg9XvwWIw4N22uu837Kng0Qj30Nbx0pC36DhhE1Opr2oUZyMjnQZ0WTxSvfs29rdJ2mxCUNUgCPopA=w2400)

---
Bên trên là xong giai đoạn dùng git rebase **Cơ bản** và nói chung là ta có thể dùng cách này để làm việc.

`Nhưng` có một vấn đề nho nhỏ là nếu nhánh `feature` ta cứ liên tục commit kiểu sợ mất `code` thì sẽ dẫn đến là sẽ có rất nhiều commit của nhánh `feature` sẽ gắn vào trong list commit của nhánh `master` sau khi ta dùng lệnh `git merge feature`. Nếu điều này không phiền bạn thì thôi. Nhưng mà nếu nó **Phiền** bạn quá thì ta sẽ tiếp tục giải quyết nó thôi.

> Cách giải quyết là đứng tại nhánh `feature` khi rebase nhánh `master` vào thì ta dùng lệnh `git rebase -i master` và cụ thể thì đọc tiếp nào.

Tiếp tục câu chuyện bên trên thì ta tiếp tục làm nhánh `feature` và commit `branch 4` và `branch 5` vào nhánh đó.
Đồng thời nhánh remote/master cũng có thêm commit `master 4`. Do đó ta phải pull nhánh remote/master về local/master với lệnh `git checkout master && git pull` và cụ thể thì dưới hình sau
![prepare-next-rebase](https://lh3.googleusercontent.com/CJqRahRXbYW4q_5TGUt6Sn7slWhT8RUruKx6lxe4oEHXUiQ0JXfgHMVJVwAgOIRlwOddNqfG7sxh0bsKfZGct2F5mhhgAcWKk_3UyuCBBEiWQU-5RnTiiAJGM5WMOFXoveSzvjnMqg=w2400)

Sau khi đứng tại nhánh `feature` và dùng lệnh `git rebase -i master` thì ta sẽ được git mở ra một sửa số mới thứ nhất như hình
![git-rebase-i-master-first-window-1](https://lh3.googleusercontent.com/2nj9i7G2MC5JdUcA1KYmQd8wFrb3t_YdqsJDUWlTzVv1TfGEauXTs-lmwm4gg2aXqcljwWkyLjkDNEzKtqzEfqntpa-bxop6QQpSKSXCrvWzJkA4rKzr7huSHpXuBnwVD6nuxKV1BA=w2400)
Giới thiệu tí thì đây là cửa sổ dùng để chỉnh sửa toàn bộ commit của nhánh `feature` tính từ thời điểm `update` nhất với master. Với cửa sổ này thì ta lưu ý:
- Cửa sổ này dùng lệnh của `vim` với `i` là insert mode để gõ text, `:w` save lại `:q` là thoát, `esc` trở về chế độ `normal`
- Commit sẽ list theo thứ tự mới phía dưới, cũ bên trên
- Commit đầu tiên phải giữ và nếu muốn thay đổi message của commit thì nên dùng lệnh `reword` hay `r`
- Commit nào muốn giữ `code` nhưng không muốn giữ `message` thì dùng lệnh `fixup` hay `f` phía trước commit-hash number của commit đó

![git-rebase-i-master-first-window-2](https://lh3.googleusercontent.com/b0Jw-JEZnDPZbtpu9r1QLqWAfmIV_FNtKXIs4hMQwsPk1cDbXZIVSoWK5aIYoIqfQy4pPvi9-04-8hUD5zzS1ayhHVwycxjrUzqvvhYKnSQlGpcWrFEAv8CoU12lWI9QnbbPVCRR2Q=w2400)

Sau khi chỉnh sửa ưng ý thì ta dùng lệnh save, quit là `:wq` và tiếp tục tới cửa sổ tiếp theo như hình dưới 

![git-rebase-i-master-second-window](https://lh3.googleusercontent.com/QYH5jw003y7W6BQx1rXX-Vz-YIceB6nDVOYZ8-RqX5ezC_-I3CVDC4piQqkG8a_nYMKrsEDnF4FlUzniEgxu85Q0aeMDOKIithUBRRqF6j6jb_LqO9UT4Y8jGZ1XaRTrTEriu-gUYg=w2400)

Tiếp tục dùng `vim` để chỉnh sửa message cho ưng ý như xong rồi save, quit như hình dưới ![git-rebase-i-master-second-window-2](https://lh3.googleusercontent.com/SwceFnBTkBOSTUK9atJf483oN1XG3dOVtw2hcH6OqaER34cgPbI0O8rDBjrlxVpZFvlis-BIrZ1TJXQDC-BhhH79a8s0TMqm4CFzA3C4sULLCc3XozZ0nSP5PdH-OlTRPYcC9pfywA=w2400)

Sau khi hoàn thành bước phía trên thì việc tiếp theo là của git sẽ làm việc và sau đó thì ta có kết quả kiểm tra theo hình phía dưới
![git-rebase-i-master-result](https://lh3.googleusercontent.com/tm5F_GuYYXxSRxnt56IF5Gb4rctq5LainJRhUA3kCu2mmPiw2gqoCtK7ZyOzAoTpjtW69CXePqLivaOZN2ND0Yuyp_Lw9AvPw_QoVjkPyKegq7HDtwQa-gMT3ydCE-KeZ9mJFSKljw=w2400)

Cụ thể kết quả sau lần dùng lệnh `git rebase -i master` thì ta có gì nào
1. Nhánh `feature` đã gộp thành công 2 commit `branch 4` và `branch 5` vào thành 1 commit mới có code bao gồm cả 2 commit nhưng chỉ có 1 message mới
2. Commit của nhánh `feature` đã nằm **SAU** commit của nhánh `master`

Việc tiếp theo là `git checkout master` và `git merger feature` để update nhánh `master` theo hình dưới
![git-merge-feature](https://lh3.googleusercontent.com/6OHLfr_MUTLis5uQzHtJhIeHQ2KpLRxMDIq0QMwFPvNuKA9G0uT61XliSIxkvrYndTSGcGNxeMqT4AEqPhWnG54yLfLf8QwVZtGWfDLCVcS-u2OL888yTopr19CEYCGbomjdlP-0HQ=w2400)


{{< typeit >}}
**Mời các thánh chém. Hết bài...**
{{< /typeit >}}


