Cách chia công việc để tránh conflict khi merge code và cách xử lí conflict trên GIT

Có ai chia sẽ giúp mình về kinh nghiệm phân chia task làm việc để khi code hạn chế việc code bị conflict khi merge với thành viên khác ?

Trên GIT, khi conflict code xảy ra thì mọi người hay xử lí conflict như thế nào? Xử lí bằng cách review code và sửa bằng tay hay dùng một tool nào ? Cám ơn.

1 Like

Conflict có thể xảy ra ở một module chung mà mọi người trong team cùng dùng và chỉnh sửa. Cách đơn giản để xử lý conflict là so sánh. Bạn sẽ luôn có 1 bản clone và 1 bản dev, khi bắt đầu merge hay rebase thì bạn copy nguyên cái gốc (ở bản clone mới nhất), sau đó update phần bạn làm ở phía cuối.

5 Likes

Mình chưa hiểu phần copy nguyên cái gốc lắm.
Có phải khi merge thí copy 1 bản ra để backup hả bạn?

Với lại có 1 vấn đề nữa, Khi các nhóm bắt đầu làm các nhiệm vụ khác nhau, họ clone ở master về, sau đó làm phần của họ. Khi mình merge thì nhóm đầu tiên sẽ rất nhàn vì họ thay đổi gì so với master là mình biết. Nhưng các nhóm sau thì khó quá vì các nhóm sau thay đổi so với master ban đầu và master lại thay đổi so với ban đầu vì đã ghép với nhóm đầu tiên. Dẫn đến nhóm sau thay đổi rất nhiều mà mình khó biết được thay đổi những phần nào.

Mong các bạn chỉ cách.

2 Likes

Ý bạn là so sánh changes của nhóm thứ 2, 3, 4… so với master ban đầu hay master sau khi được merged với nhóm 1? Nếu là so với master ban đầu thì cách của mình là lùi về HEAD^1 (HEAD^1 là master trước khi merge) rồi diff với branch của nhóm 2, 3, 4…

1 Like

mình muốn tại master đã merge với nhóm 1. so sánh với các nhóm khác để merge tiếp ý bạn. Thực sự hơi khó.

Cách của mình vẫn làm là luôn thực hiện pull trước khi push.
Người push sau sẽ thực hiện diff nếu gặp conflic, tiếp theo là merge các đoạn code được đánh dấu <<<<<<<<< >>>>>>>>> với nhau.

Hiện tại thì chỉ có cách thủ công đó. (Mình dùng terminal nên không biết bên GUI có phần giao diện để select không)

2 Likes

Mình đang cho 3 nhóm làm 3 nhánh khác nhau, khi họ làm xong, push lên, mình sẽ checkout sang nhánh của họ xem thay đổi gì và gộp nó vào bằng tay những thay đổi đó.

Do vậy các đoạn code đánh dấu <<<<<<>>>>>>> sẽ không xuất hiện.

Mà cùng 1 nhánh, nhiều khi họ push lên, sau mình checkout sang nhánh của họ và pull nhánh của họ về mà dùng git diff nó chả hiện cái gì hết.

3 Likes

vậy là 2 người tuyệt đối không được code chung một file ạ ? nhỡ như có trường hợp các chức năng cùng chung 1 file thì sao ?

1 Like

trường hợp này chỉ có thể giảm tối đa chứ không thể tránh:

  • nếu là file không cần commit thì đưa vào gitignore
  • đối với file có thể chia tách được thì chia tách thành file riêng biệt

các trường hợp còn lại phải merge thủ công nếu conflicts

4 Likes

GitKraken có chức năng này bác ơi :v

2 Likes

Nguyên tắc của tôi là trước khi commit đều phải pull (update) code của mn về. (conflic thì conflic ở máy local, sửa conflic rồi mới push code lên git)
Kinh nghiệm của tôi là cố gắng chia task để k phải làm chung file (tại 1 thời điểm).
Khi cv bắt buộc phải code chung thì (đối với người chưa quen):
trước khi pull code về thì copy code đã sửa sang 1 nơi khác (có thể là notepad)
revert lại phiên bản trước khi sửa -> pull code về (chắc chắn k conflic) -> copy những đoạn mình mới code thêm vào code mới -> push code lên git.
Trước khi ấn ok của commit thì nhớ xem lại review xem có xóa nhầm của ai không!
Còn người làm quen rồi thì pull code về bth, có conflic thì sửa và push code. (xử lý conflic thì chú ý kẻo làm mất code của người khác - tôi đã là nạn nhân - đi mò bug muốn xỉu)

5 Likes

Thường thì mình sẽ làm như thế này

  1. Nếu 2 người code cùng 1 branch
  • Trước khi code: pull
  • Code xong: fetch
  • Nếu không thấy có commit mới thì chỉ cần commit và push thôi.
  • Nếu thấy có commit mới?
    – Tạo một branch tạm, commit vào đó
    – Quay lại branch chính, pull code về
    – Cherry pick commit từ branch tạm
    – Nếu có conflict thì 2 người ngồi lại review rồi pick, nếu không thể thì cố gắng liên lạc trao đổi, tránh làm mất code của người khác
    – Merge xong thì chạy lại kiểm tra, vì đôi khi merge không có conflict nhưng vẫn làm cho app chạy sai, ví dụ 1 người +1 biến X ở đoạn code trên, 1 người +1 biến X ở đoạn code dưới, 2 đoạn code làm X +2
    – Resolve xong thì push lên
  1. Trường hợp cần merge 2 nhánh
  • Mình chỉ merge 2 nhánh nếu 2 nhánh đó đều mới nhất (tức là local == remote)
  • Merge branch chính vào branch phụ (định nghĩa thế nào thì tuỳ bạn, nhưng ngoại lệ là master, branch này không xoá được, vì vậy chỉ merge master vào branch khác, nhỡ push có gì sai sót mình chỉ cần quay về commit đúng, xoá nhánh đi rồi push lại nhánh đó lên là xong, các commit reverse sẽ làm tree nhìn rất rối
  • Sau khi mọi thứ đã ok thì update branch chính, lúc này không cần merge vì không có commit nào mới nữa
4 Likes

hi ! Em gặp trường hợp như này, có 3 người A, B, C cùng code chung 1 file project.txt ( không thể chia nhỏ file này nữa )

  • A thêm vào “hi tôi là A” commit rồi push lên.
  • B thêm vào “hi tôi là B” chưa fetch, chưa commit luôn.
  • trong lúc đó C cũng đang ngồi code “hi tôi là C”.

==== > lúc B và C code đã xong khi fetch thì được báo project.txt bị thay đổi, C và D commit được nhưng không thể push code lên và cũng không thể pull xuống.

Đáng lẽ file project.txt cuối cùng sẽ có nội dung là :
hi tôi là A
hi tôi là B
hi tôi là C
—> A không bị lỗi
—> B & C bị lỗi do file project.txt trên repo local khác với trên sever ?

Cho em hỏi lỗi này fix sao ạ ? vì trước giờ em đang code mà nó người sửa file em đang làm là bị lỗi ngay :cry: thanks mn ! ^^

1 Like

Khi commit lên nhánh local, B và C tạo một branch riêng là b, và c, rồi quay lại branch kia, reset về origin, pull về. Quay sang nhánh b, c rồi merge, quay lại nhánh chính merge cái commit đã merge kia vào.

7 Likes

Simulate trường hợp này thì quá trình như sau:
Bước 1:

  • Trên remote: …commit1—>commit2—>commit3
  • Trên máy A: …commit1—>commit2—>commit3—>commit4A(“hi tôi là A”)
  • Trên máy B: …commit1—>commit2—>commit3—>commit4B(“hi tôi là B”)
  • Trên máy C: …commit1—>commit2—>commit3—>commit4C(“hi tôi là C”)

Bước 2:

  • A chạy: git push nên commit trên máy A được đẩy lên remote
  • Vì thế lúc này trên remote sẽ là: …commit1—>commit2—>commit3—>commit4A(“hi tôi là A”)

Bước 3:

  • B chạy: git push, nhưng không push được vì remote đã có commit4A từ A, bắn ra lỗi
    Updates were rejected because the remote contains work that you do not have locally., yêu cầu B chạy git pull
  • B chạy: git pull
  • commit4A(“hi tôi là A”) từ remote được pull về, xung đột với commit4B(“hi tôi là B”), vì git ko hiểu có nên giữ cái dòng “hi tôi là A” hay không (do commit4B(“hi tôi là B”) mới nhất trên máy B cũng không có đề cập tới dòng này). Vì vậy git sẽ đánh dấu như sau:
<<<<<<< HEAD 
hi toi la B 
======= 
hi toi la A
>>>>>>> a9935c71ee5f1ede1843e16f4d0f27813ffeb30a

yêu cầu B merge thủ công và tạo thành 1 commit5(“hi tôi là A”, “hi tôi là B”) trước khi push lên.

  • B merge xong, tạo commit5(“hi tôi là A”, “hi tôi là B”) và chạy: git push
  • Lúc này remote sẽ là: …commit1—>commit2—>commit3—>commit4A(“hi tôi là A”)—>commit4B(“hi tôi là B”)—>commit5(“hi tôi là A”, “hi tôi là B”)

Bước 4
-Trường hợp của C thì y như B

10 Likes

@TyE Anh ơi khi làm project nhóm, em nên mời thành viên access vào làm collaborators luôn hay để thành viên fork về , code xong, tự tạo pull request rồi em review code sau đó em merge vào nhánh master vậy anh ?

2 Likes

khi merge 1 task chức năng nào đó cùng 1 file cũng chẳng liên quan gì đến nhau ở những task khác khi cũng xử lý ở file ấy, mỗi branch là 1 nhánh riêng biệt, code của bạn sẽ không liên quan đến người khác, nếu người trước đó được merge cùng file ấy vào develop hoặc master, việc cần làm của bạn là pull code mới nhất từ branch develop về local và tiến hành merge vào branch mình đang làm -> đây là lúc xảy ra conflict, hãy lấy tất cả code từ bên develop(bắt buộc) và bên nhánh mình chỉ lấy những phần mình code và push lên repo thôi

2 Likes

đúng òi đó, fork và tạo pull request.
nên có tối thiểu 2 nhánh dev và master (thêm nhánh beta, alpha,… gì đó tùy quy trình của nhóm nhưng đơn giản thì chỉ cần 2 nhánh):

  • nhánh master là nhánh stable, không thay đổi nhiều, không ai commit trực tiếp vào mà phải thông qua pull từ dev vào, nghĩa là chỉ chứa các phiên bản với tag v1.0, v1.1,… ready to run, chỉ cần checkout là chạy.
  • nhánh dev là nhánh không ổn định. Được checkout -b từ nhánh master lúc bắt đầu project, code hằng ngày của nhóm sẽ đưa vô nhánh dev.

khi nào nhánh dev cần chốt phiên bản thì mới pull từ dev vào master, gắn tag phiên bản.

11 Likes

Khi muốn “quay về quá khứ” tại một commit chỉ định thì tạo nhánh trước (git switch) rồi mới git restore hay restore trước rồi mới tạo nhánh ạ?

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