Git'te Anlaşmazlıkları Anlama ve Çözme

İşte her geliştiricinin görmekten nefret ettiği kelime: çatışma. ? Git (veya diğer sürüm kontrol sistemleri) ile çalışırken ara sıra meydana gelen birleştirme çatışmasını aşmanın yolu yoktur.

Ancak geliştiricilerle konuşurken, sık sık birleştirme çatışmaları konusunda bir endişe veya rahatsızlık hissi olduğunu duyuyorum .

Çatışmaların üstesinden gelmek genellikle karanlık, gizemli bir yer olarak kalır: işlerin kötü bir şekilde kırıldığı ve bundan nasıl çıkılacağının belirsiz olduğu (işleri daha da kötüleştirmeden) bir durum.

Birleştirme çatışmalarının bir geliştiricinin hayatının kaçınılmaz bir parçası olduğu doğru olsa da, bu durumlardaki rahatsızlık tamamen isteğe bağlıdır.

Bu makaleyle ilgili amacım, bu konuya biraz açıklık getirmek: çatışmalar tipik olarak nasıl ve ne zaman ortaya çıkıyor, gerçekte ne oldukları ve bunların nasıl çözüleceği veya geri alınacağı.

Bunları doğru bir şekilde anladığınızda, birleştirme çatışmalarıyla çok daha rahat ve kendinden emin bir şekilde başa çıkabileceksiniz. ?

Çatışmalar Nasıl ve Ne Zaman Oluşur?

İsim zaten şunu söylüyor: "Birleştirme çatışmaları" farklı bir kaynaktan gelen taahhütleri entegre etme sürecinde ortaya çıkabilir.

Yine de, "entegrasyonun" yalnızca "dalları birleştirmek" ile sınırlı olmadığını unutmayın. Aynı zamanda, yeniden pazarlama veya etkileşimli yeniden satış sırasında, bir kiraz toplama veya çekme gerçekleştirirken veya bir Stash'i yeniden uygularken bile olabilir.

Tüm bu eylemler bir tür entegrasyon gerçekleştirir ve işte o zaman birleştirme çatışmaları olabilir.

Ancak elbette, bu eylemler her seferinde bir birleştirme çatışmasıyla sonuçlanmaz (Tanrıya şükür!). İdeal olarak, kendinizi bu gibi durumlarda bulmanız çok nadirdir. Ama çatışmalar tam olarak ne zaman ortaya çıkıyor?

Aslında, Git'in birleştirme yetenekleri en büyük avantajlarından biridir: Dalları birleştirmek çoğu zaman zahmetsizce çalışır, çünkü Git genellikle işleri kendi başına çözebilir.

Ama durumlar vardır çelişkili değişiklikler ve teknoloji basitçe nerede - yapılmıştır edemez doğru ya da yanlış ne olduğuna karar. Bu durumlar basitçe bir insanın kararını gerektirir.

Gerçek klasik, iki farklı dalda iki işlemde aynı kod satırının değiştirilmesidir. Git'in hangi değişikliği tercih ettiğinizi bilmesinin bir yolu yok! ?

Bazı başka benzer durumlar da vardır - örneğin, bir dosya bir dalda değiştirilip başka bir dalda silindiğinde - ancak bunlar biraz daha az yaygındır.

"Kule" Git masaüstü GUI , örneğin, bu tür durumlarla görselleştirme güzel yolu vardır:

Bir Çatışmanın Ne Zaman Ortaya Çıktığını Nasıl Anlarsınız?

Endişelenmeyin: Git bir çatışma olduğunda size çok net bir şekilde söyleyecektir. ?  

Birincisi, örneğin bir çatışma nedeniyle bir birleştirme veya yeniden ödeme başarısız olduğunda anında size haber verecektir :

$ git merge develop Auto-merging index.html CONFLICT (content): Merge conflict in index.html CONFLICT (modify/delete): error.html deleted in HEAD and modified in develop. Version develop of error.html left in tree. Automatic merge failed; fix conflicts and then commit the result.

Yukarıdaki örnekten de görebileceğiniz gibi, bir birleştirme yapmayı denediğimde bir birleştirme çakışması yarattım - ve Git sorunu çok net ve hızlı bir şekilde iletiyor:

  • "İndex.html" dosyasında bir çakışma meydana geldi.
  • "Error.html" dosyasında başka bir çakışma oluştu.
  • Ve son olarak, çatışmalar nedeniyle, birleştirme işlemi başarısız oldu.

Bunlar, kodu araştırmamız ve ne yapılması gerektiğini görmemiz gereken durumlar.

Çakışma meydana geldiğinde bu uyarı mesajlarını gözden kaçırdığınız beklenmedik bir durumda, Git ayrıca her çalıştırdığınızda sizi bilgilendirir git status:

$ git status On branch main You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add/rm ..." as appropriate to mark resolution) deleted by us: error.html both modified: index.html

Başka bir deyişle: birleştirme çatışmalarını fark etmeme konusunda endişelenmeyin . Git onları gözden kaçırmamanızı sağlar.

Git'te Bir Çakışmayı Geri Alma ve Baştan Başlama

Birleştirme çatışmaları belirli bir aciliyet havasıyla birlikte gelir. Ve haklı olarak: işinize devam etmeden önce onlarla ilgilenmeniz gerekecek.

Ancak bunları görmezden gelmek bir seçenek olmasa da, "birleştirme çatışmalarıyla uğraşmak" mutlaka bunları çözmeniz gerektiği anlamına gelmez. Geri alınıyor onları da mümkündür!

Bu tekrar etmeye değer olabilir: her zaman bir birleştirme çatışmasını geri alma ve önceki duruma geri dönme seçeneğiniz vardır. Bu, çakışan dosyaları çözmeye başladığınızda ve kendinizi bir çıkmazda bulduğunuzda bile geçerlidir.

Bu durumlarda, her zaman yeniden başlayabileceğinizi ve çatışma gerçekleşmeden önce temiz bir duruma dönebileceğinizi unutmamak harika.

For this purpose, most commands come with an --abort option, for example git merge --abort and git rebase --abort:

$ git merge --abort $ git status On branch main nothing to commit, working tree clean

This should give you the confidence that you really cannot mess up. You can always abort, return to a clean state, and start over.

What Conflicts Really Look Like in Git

Now, safe in the knowledge that nothing can break, let's see what a conflict really looks like under the hood. This will demystify those little buggers and, at the same time, help you lose respect for them and gain confidence in yourself.

As an example, let's look at the contents of the (currently conflicted) "index.html" file in an editor:

Git was kind enough to mark the problem area in the file, enclosing it in <<<<<<< HEAD and >>>>>>> [other/branch/name]. The content that comes after the first marker originates from our current working branch. Finally, a line with ======= characters separates the two conflicting changes.

How to Solve a Conflict in Git

Our job as developers now is to clean up these lines: after we're finished, the file has to look exactly as we want it to look.

It might be necessary to talk to the teammate who wrote the "other" changes and decide which code is actually correct. Maybe it's ours, maybe it's theirs - or maybe a mixture between the two.

This process - cleaning up the file and making sure it contains what we actually want - doesn't have to involve any magic. You can do this simply by opening your text editor or IDE and starting to making your changes.

Often, however, you'll find that this is not the most efficient way. That's when dedicated tools can save time and effort:

  • Git GUI Tools: Some of the graphical user interfaces for Git can be helpful when solving conflicts. The Tower Git GUI, for example, offers a dedicated "Conflict Wizard" that helps visualize and solve the situation:
  • Dedicated Merge Tools: For more complicated conflicts, it can be great to have a dedicated "Diff & Merge Tool" at hand. You can configure your tool of choice using the "git config" command. (Consult your tool's documentation for detailed instructions.) Then, in case of a conflict, you can invoke it by simply typing git mergetool. As an example, here's a screenshot of "Kaleidoscope" on macOS:

After cleaning up the file - either manually or in a Git GUI or Merge Tool - we have to commit this like any other change:

  • By using git add on the (previously) conflicted file, we inform Git that the conflict has been solved.
  • When all conflicts have been solved and added to the Staging Area, you need to complete the resolution by creating a regular commit.

How to Become More Confident and Productive

Many years ago, when I started using version control, merge conflicts regularly freaked me out: I was afraid that, finally, I had managed to break things for good. ?

Only when I took the time to truly understand what was going on under the hood was I able to deal with conflicts confidently and efficiently.

The same was true, for example, when dealing with mistakes: only once I learned how to undo mistakes with Git was I able to become more confident and productive in my work.

I highly recommend taking a look at the free "First Aid Kit for Git", a collection of short videos about how to undo and recover from mistakes with Git.

Have fun becoming a better programmer!

About the Author

Tobias Günther is the CEO of Tower, the popular Git desktop client that helps more than 100,000 developers around the world to be more productive with Git.