Câu hỏi về git rebase

Chào mọi người, mình có thấy một câu hỏi về git nhưng chưa hiểu rõ tình huống thực tế của nó lắm trên stackoverflow

Mình mô tả lại như sau, sau một loạt các bước rebase thì git graph sẽ như sau

A <----- B <-------- C ' (v1)
            \
             ----------C '' (main)

Mục đích tác giả muốn thay đổi history của main branch thành

A <----- B <-------- C ' <------- C'''

Theo như answer, sau khi chạy lệnh

git reset --soft v1

thì mình chạy lệnh

git commit -m "C''' " 

nó báo lỗi không tìm thấy commit C’’’ mà mình phải tạo một commit mới với message C’’’ thì ra được đúng yêu cầu.

Mình có đọc phần comment ở dưới những vần chưa hiểu vấn đề lắm

Mong mọi người giải đáp thêm, cám ơn mọi người.

git commit -C <sha_commit_index> chứ không phải commit message

thường bạn có thể sử dụng git reflog để tìm sha id:


**102b900** (HEAD -> main) [email protected]{0}: commit: feat: test.xt
**1d4a96d** (feat/test) [email protected]{1}: reset: moving to feat/test
**a12a938** (origin/main, origin/HEAD) [email protected]{2}: checkout: moving from feat/test to main

thì tương ứng bạn có thể git commit -C 1d4a96d

Thông thường các git GUI đều hỗ trợ tìm commit index trên nhiều branches

Git rebase được dùng rất nhiều trong git workflows, công ty mình đặt luôn luật là feature branches cần rebase với develop thì mới được merge (fast-forward). Việc dùng reset --soft để tránh việc feature branch có quá nhiều conflicts và việc rebase rất khó khăn, reset cũng có thể dùng để squash commit luôn

4 Likes

Cám ơn bạn, nhận tiện việc bạn nói về workflow ở dưới. Mình có một vài ý kiến như sau.

Thứ nhất, bạn có thể cho mình biết tại sao ở công ty bạn lại đặt luật là phải rebase develop branch vào feature branch thì mới được merge lại, sau đó merge lại thì nó lại là fast-forward được không?

Về chỗ này, thì mình biết có 2 cách để tích hợp code, 1 là dùng rebase, 2 là dùng merge để cập nhập code từ develop vào nhánh feature, tuỳ thuộc vào mục đích muốn xây dụng history thế nào để chọn, còn về mục đích tại sao lại chọn history như vậy thì mình cũng chưa có kinh nghiệm đánh giá. Mình cũng nhắc lại, sự khác biệt cơ bản giữa 2 phương pháp trên là git rebase sẽ không tạo ra commit mới, còn git merge sẽ tạo ra commit mới, nhưng việc dùng rebase nó khiến cho mốc thời gian rất lộn xộn, đôi khi commit mới nhất về thời gian lại đứng sau commit khác. Dĩ nhiên không phải lúc nào git merge cũng tạo ra commit mới, nọ phụ thuộc vào HEAD của nhánh được merge có thay đổi (thêm commit) so với lúc tạo ra nhánh feature hay không, đây chính là trường hợp fast-forward như bạn nói. Phần tiếp theo, bạn nói thế này thì mình cũng chưa hiểu rõ ý bạn lắm.

Thứ hai, về việc dùng reset --soft để tránh conflict thì mình cũng không đồng tình lắm. Mình nghĩ khi tích hợp hợp thì việc solve confict là điều rất khó tránh khỏi, hơn nữa việc dùng reset --soft chỉ là kết quả của việc muốn giữ lại nhưng thay đổi khi quay lại một commit nào đó trong quá khứ.

Cuối cùng, không biết có phải bạn nhầm không, theo mình biết squash commit dùng rebase chứ reset sao có thể.

Git Reset Soft
This option moves HEAD back to the specified commit, undoes all the changes made between where HEAD was pointing and the specified commit, and saves all the changes in the index. In other words, Git re-adds the changes as staged, ready to be committed again.

trích từ GitKraken

2 Likes

Nope, công ty mình rebase feature branch vào develop trước khi merge. Workflow này do mình đề xuất và trình bày ở công ty, lúc đầu cũng có 1 vài người phản đối trong đó có cả senior. Sau 2 tháng thì không ai muốn quay lại workflow cũ cả, nhất là project manager.

Mục đích là để tạo linear history và quan trọng nhất vẫn là để các thành viên commit cần phải biết chuyện gì đang xảy ra ở develop. Feedback mình nhận được là mặc dù developers có vẻ vất vả hơn trong việc quản lý các branch nhưng làm việc đó giúp họ hiểu rõ hơn về cấu trúc của codebase.

Việc tìm kiếm các commit trong history cũng đơn giản hơn rất nhiều.

Nope, cơ mà tránh conflict trong quá trình rebase. Nếu feature branch của bạn có 20-30 commits ahead of develop thì trong quá trình rebase bạn sẽ phải resolve conflict trong mỗi commits (nếu có)

squash là 1 option trong quá trình rebase

P/S: Mình có làm agile consulting cho công ty nào hiện đang gặp rắc rối về mặt quản lý và workflow!

2 Likes

Bạn có thể làm rõ hơn đoạn này được không, mình hơi bị confuse một chút. Theo như mình hiểu, khi chúng ta code trên nhánh feature xong, điều chúng ta cần tiếp theo là cần update code ở develop branch (đoạn này mình thường hay nói là rebase develop vào feature) cũng như là resolve conflict nếu có. Tại sao bạn lại ghi ngược lại nhỉ?, hay mục đích của bạn là gì khác.

Như mình có nói lúc đầu, nhìn thì có vẽ là linear, nhưng thực chất thì lại không phải, vì rebase A vào B ,sẽ chuyển các commit của riếng A lên đầu của nhánh B, do vậy về mặt thời gian thì nó không được đảm bảo, nghĩa là có những commit của ngày hôm kia nhưng lại đứng sau commit của ngày hôm qua chẳng hạn.

Đoạn này thì mình nhất chí, nhưng cái mình thắc mắc không phải là điều này, nhưng không sao, @rogp10 đã trả lời phía trên, chỉ là mình thấy ít người dùng reset --soft để squash commit.

Mình có đọc về git reset --soft trên GitKraken, mình thấy chỉ mô tả trường hợp squash n commit mới nhất, vậy còn trường hợp muốn squash n commit ở giữa thì sao, mình chưa hình dung ra được.

Theo mình sẽ có một vài bước như sau:
Giả sử history như sau: mình cần squash A4 về A1, gọi là A’
first commit <--------A <-------A1 <-------A2 <-------A3 <--------A4 <----B1 <----- B2<------ lastest commit

  • Đầu tiên là detachted HEAD về A4, và tạo một branch f
  • Trên branch f, mình reset --soft về A, sau đó add, commit A’
  • Cuối cùng là có thể là dùng merge hoặc rebase (đoạn này mình không chắc)

Vậy thực sự nó sẽ thế nào nhỉ? Bạn giải đáp giúp mình.

Không, bạn viết đúng rồi. Để ý lại thì mới thấy m viết ngược đó

Với cty mình thì ngày tạo commit không quan trọng bằng ngày merge commit vào develop.

2 Likes

Ok, thank you. A good discussion.

1 Like

Case này thì rebase interactive về first commit, rồi squash A1, A2, A3 vào A4 là xong

p lastest
p B2
p B1
p A4
s A3
s A2
s A1
p A
git rebase -i [first commit]

Mình biết và thường dùng git rebase -i, nhưng mình đang muốn làm rõ về việc dùng git reset --soft@rogp10 đã nói

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?