Git Sıfırlama vs Geri Döndürme vs Rebase

Yayınlanan: 2021-05-20

Bu makalede, Git'te taahhütlerle oynamanın farklı yollarını öğreneceksiniz.

Bir geliştirici olarak, önceki taahhütlerinizden birine geri dönmek isteyebileceğiniz ancak bunu nasıl yapacağınızdan emin olmadığınız bu tür durumlarla birden çok kez karşılaşırsınız. Ve reset, revert, rebase gibi Git komutlarını bilseniz bile aralarındaki farkların farkında değilsiniz. Öyleyse başlayalım ve git reset, revert ve rebase'in ne olduğunu anlayalım.

Git Sıfırla

Git reset karmaşık bir komuttur ve değişiklikleri geri almak için kullanılır.

Git sıfırlamayı bir geri alma özelliği olarak düşünebilirsiniz. Git sıfırlama ile çeşitli taahhütler arasında geçiş yapabilirsiniz. Git reset komutunu çalıştırmanın üç modu vardır: –soft, –mixed ve –hard. Varsayılan olarak git reset komutu karma modu kullanır. Git sıfırlama iş akışında, git'in üç dahili yönetim mekanizması devreye girer: HEAD , hazırlama alanı (index) ve çalışma dizini .

git sıfırlama - geekflare

Çalışma dizini, şu anda çalıştığınız yerdir, dosyalarınızın bulunduğu yerdir. Bir git status komutu kullanarak, çalışma dizininde tüm dosya/klasörlerin neler olduğunu görebilirsiniz.

Aşama Alanı (İndeks), git'in dosyalardaki tüm değişiklikleri izlediği ve kaydettiği yerdir. Kaydedilen değişiklikler .git dizinine yansıtılır. Dosyayı hazırlama alanına eklemek için git add “filename” kullanırsınız. Ve daha önce olduğu gibi, git durumunu çalıştırdığınızda, hazırlama alanında hangi dosyaların bulunduğunu göreceksiniz.

Git'teki mevcut dal HEAD olarak adlandırılır. Geçerli ödeme dalında gerçekleşen son işleme işaret eder. Herhangi bir referans için bir işaretçi olarak kabul edilir. Başka bir şubeye ödeme yaptığınızda, HEAD de yeni şubeye taşınır.

Git sıfırlamanın sert, yumuşak ve karışık modlarda nasıl çalıştığını açıklamama izin verin. Zor mod, sivri taahhüde gitmek için kullanılır, çalışma dizini bu taahhüdün dosyalarıyla doldurulur ve hazırlama alanı sıfırlanır. Yazılım sıfırlamada, yalnızca işaretçi belirtilen işleme değiştirilir. Tüm taahhütlerin dosyaları, sıfırlamadan önce çalışma dizininde ve hazırlama alanında kalır. Karışık modda (varsayılan), işaretçi ve hazırlama alanı sıfırlanır.

Git Sert Sıfırla

Git sert sıfırlamanın amacı, HEAD'i belirtilen işleme taşımaktır. Belirtilen taahhütten sonra gerçekleşen tüm taahhütleri kaldıracaktır. Bu komut, taahhüt geçmişini değiştirecek ve belirtilen taahhüdü işaret edecektir.

Bu örnekte, üç yeni dosya ekleyeceğim, onları işleyeceğim ve ardından donanımdan sıfırlama yapacağım.

Aşağıdaki komuttan da görebileceğiniz gibi, şu anda taahhüt edilecek bir şey yok.

 $ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean

Şimdi 3 dosya oluşturacağım ve ona biraz içerik ekleyeceğim.

 $ vi file1.txt $ vi file2.txt $ vi file3.txt

Bu dosyaları mevcut depoya ekleyin.

 $ git add file*

Status komutunu tekrar çalıştırdığınızda, az önce oluşturduğum yeni dosyaları yansıtacaktır.

 $ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: file1.txt new file: file2.txt new file: file3.txt

Taahhüt etmeden önce size göstereyim, şu anda Git'te 3 taahhüt günlüğüm var.

 $ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test

Şimdi, depoya söz vereceğim.

 $ git commit -m 'added 3 files' [master d69950b] added 3 files 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txt

Eğer ls-files yaparsam, yeni dosyaların eklendiğini göreceksiniz.

 $ git ls-files demo dummyfile newfile file1.txt file2.txt file3.txt

Git'te log komutunu çalıştırdığımda, 4 taahhüdüm var ve HEAD en son taahhüdü gösteriyor.

 $ git log --oneline d69950b (HEAD -> master) added 3 files 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test

Dosya1.txt dosyasını manuel olarak silersem ve git durumu yaparsam, değişikliklerin taahhüt için hazır olmadığı mesajını gösterecektir.

 $ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) deleted: file1.txt no changes added to commit (use "git add" and/or "git commit -a")

Şimdi, donanımdan sıfırlama komutunu çalıştıracağım.

 $ git reset --hard HEAD is now at d69950b added 3 files

Durumu tekrar kontrol edersem, yapılacak bir şey olmadığını ve sildiğim dosyanın havuza geri geldiğini göreceğim. Geri alma, dosyayı sildikten sonra taahhütte bulunmadığım için gerçekleşti, bu nedenle donanımdan sıfırlama işleminden sonra önceki durumuna geri döndü.

 $ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean

Git günlüğünü kontrol edersem, böyle görünecek.

 $ git log commit d69950b7ea406a97499e07f9b28082db9db0b387 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 19:53:31 2020 +0530 added 3 files commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 test

Donanımdan sıfırlamanın amacı, belirtilen taahhüdü işaret etmek ve çalışma dizinini ve hazırlama alanını güncellemektir. Size bir örnek daha göstereyim. Şu anda, taahhütlerimin görselleştirmesi aşağıdaki gibi görünüyor:

git zor

Burada komutu HEAD^ ile çalıştıracağım, bu da önceki işleme sıfırlamak istediğim anlamına geliyor (bir taahhüt geri).

 $ git reset --hard HEAD^ HEAD is now at 0db602e one more commit

Baş işaretçisinin şimdi d69950b'den 0db602e'ye değiştiğini görebilirsiniz.

 $ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test

git zor 1

Günlüğü kontrol ederseniz, d69950b taahhüdü gitti ve kafa şimdi 0db602e SHA'yı gösteriyor.

 $ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 Test

ls dosyalarını çalıştırırsanız, file1.txt, file2.txt ve files3.txt dosyalarının artık depoda olmadığını görebilirsiniz, çünkü bu taahhüt ve dosyası donanımdan sıfırlamadan sonra kaldırılmıştır.

 $ git ls-files demo dummyfile newfile

Git Yazılımdan Sıfırlama

Benzer şekilde, şimdi size bir yazılım sıfırlaması örneği göstereceğim. Düşünün, yukarıda bahsettiğim gibi 3 dosyayı tekrar ekledim ve taahhüt ettim. Git günlüğü aşağıda gösterildiği gibi görünecektir. 'Yazılımdan sıfırlama'nın en son taahhüdüm olduğunu görebilirsiniz ve HEAD de buna işaret ediyor.

 $ git log --oneline aa40085 (HEAD -> master) soft reset 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test

Günlükteki taahhüdün ayrıntıları aşağıdaki komut kullanılarak görülebilir.

 $ git log commit aa400858aab3927e79116941c715749780a59fc9 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 21:01:36 2020 +0530 soft reset commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 test

Şimdi yumuşak sıfırlamayı kullanarak, SHA 0db602e085a4d59cfa9393abac41ff5fd7afcb14 ile eski taahhütlerden birine geçmek istiyorum

Bunun için aşağıdaki komutu çalıştıracağım. SHA'nın 6'dan fazla başlangıç ​​karakterini geçmeniz gerekir, tam SHA gerekli değildir.

 $ git reset --soft 0db602e085a4

Şimdi git günlüğünü çalıştırdığımda, HEAD'in belirttiğim işleme sıfırlandığını görebiliyorum.

 $ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 test

Ancak buradaki fark, 3 dosya eklediğim taahhüt dosyalarının (aa400858aab3927e79116941c715749780a59fc9) hala çalışma dizinimde olmasıdır. Silinmemişler. Bu nedenle, donanımdan sıfırlama yerine yumuşak sıfırlama kullanmalısınız. Yumuşak modda dosyaları kaybetme riski yoktur.

 $ git ls-files demo dummyfile file1.txt file2.txt file3.txt newfile

Git Geri Dön

Git'te revert komutu, bir geri alma işlemi gerçekleştirmek, yani bazı değişiklikleri geri almak için kullanılır. Sıfırlama komutuna benzer, ancak buradaki tek fark, belirli bir işleme geri dönmek için yeni bir taahhütte bulunmanızdır. Kısacası git revert komutunun bir taahhüt olduğunu söylemek doğru olur.

Git revert komutu, geri alma işlemini gerçekleştirirken hiçbir veriyi silmez.

Diyelim ki 3 dosya ekliyorum ve geri alma örneği için bir git commit işlemi gerçekleştiriyorum.

 $ git commit -m 'add 3 files again' [master 812335d] add 3 files again 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txt

Günlük, yeni taahhüdü gösterecektir.

 $ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test

Şimdi geçmiş taahhütlerimden birine geri dönmek istiyorum, diyelim ki – “59c86c9 yeni taahhüt”. Aşağıdaki komutu çalıştırırdım.

 $ git revert 59c86c9

Bu bir dosya açacaktır, geri dönmeye çalıştığınız taahhüdün ayrıntılarını bulacaksınız ve yeni taahhüdünüze burada bir isim verebilir ve ardından dosyayı kaydedip kapatabilirsiniz.

 Revert "new commit" This reverts commit 59c86c96a82589bad5ecba7668ad38aa684ab323. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch master # Your branch is ahead of 'origin/master' by 4 commits. # (use "git push" to publish your local commits) # # Changes to be committed: # modified: dummyfile

Dosyayı kaydedip kapattıktan sonra alacağınız çıktı bu.

 $ git revert 59c86c9 [master af72b7a] Revert "new commit" 1 file changed, 1 insertion(+), 1 deletion(-)

Şimdi gerekli değişiklikleri yapmak için resetten farklı olarak revert bir yeni taahhüt daha gerçekleştirdi. Günlüğü tekrar kontrol ederseniz, geri alma işlemi nedeniyle yeni bir taahhüt bulacaksınız.

 $ git log --oneline af72b7a (HEAD -> master) Revert "new commit" 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test

git geri al

Git günlüğü, tüm taahhüt geçmişine sahip olacaktır. Taahhütleri geçmişten kaldırmak istiyorsanız, geri alma iyi bir seçim değildir, ancak taahhüt değişikliklerini geçmişte sürdürmek istiyorsanız, sıfırlama yerine geri döndürme uygun komuttur.

Git Rebase

Git'te rebase, bir dalın taahhütlerini başka bir dal üzerinde taşımanın veya birleştirmenin yoludur. Bir geliştirici olarak, gerçek dünya senaryosunda ana dalda özelliklerimi oluşturmazdım. Kendi dalımda (bir 'özellik dalı') çalışırdım ve özellik dalıma eklenen özellik ile birkaç taahhütte bulunduğumda, onu ana dala taşımak isterim.

Rebase bazen bir birleştirmeye çok benzediği için anlamak biraz kafa karıştırıcı olabilir. Her ikisini de birleştirmenin ve yeniden temellendirmenin amacı, benim özellik şubemden taahhütleri almak ve onları bir ana şubeye veya başka bir şubeye koymaktır. Düşünün, şuna benzeyen bir grafiğim var:

git rebase

Diğer geliştiricilerle bir ekipte çalıştığınızı varsayalım. Bu durumda, farklı özellik dallarında çalışan bir grup başka geliştiriciniz olduğunda ve birden çok değişikliği birleştirdiklerinde bunun gerçekten karmaşık olabileceğini hayal edebilirsiniz. İzlemek kafa karıştırıcı hale geliyor.

Yani, rebase'in yardımcı olacağı yer burasıdır. Bu sefer git merge yapmak yerine, iki özellik dalı taahhütlerimi alıp ana dala taşımak istediğim bir rebase yapacağım. Bir rebase, tüm taahhütlerimi özellik dalından alacak ve bunları ana dal taahhütlerinin üstüne taşıyacaktır. Yani, perde arkasında git, ana dalda özellik dalının taahhütlerini çoğaltıyor.

git rebase 1

Bu yaklaşım, arka arkaya tüm taahhütlerle size temiz bir düz çizgi grafiği verecektir.

git geri 2

Hangi taahhütlerin nereye gittiğini izlemeyi kolaylaştırır. Pek çok geliştiriciye sahip bir takımdaysanız, tüm taahhütlerin hala üst üste olduğunu hayal edebilirsiniz. Bu nedenle, aynı proje üzerinde aynı anda çalışan birçok kişi olsa bile takip etmesi gerçekten çok kolay.

Bunu size uygulamalı olarak göstereyim.

Ana şubem şu anda böyle görünüyor. 4 taahhüdü vardır.

 $ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test

Özellik adı verilen yeni bir dal oluşturmak ve geçiş yapmak için aşağıdaki komutu çalıştıracağım ve bu dal 2. taahhütten oluşturulacak, yani 59c86c9

 (master) $ git checkout -b feature 59c86c9 Switched to a new branch 'feature'

Özellik dalındaki günlüğü kontrol ederseniz, master'dan (ana hattan) gelen yalnızca 2 taahhüt vardır.

 (feature) $ git log --oneline 59c86c9 (HEAD -> feature) new commit e2f44fc (origin/master, origin/HEAD) test

Özellik 1 oluşturacağım ve onu özellik dalına bağlayacağım.

 (feature) $ vi feature1.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 1' [feature c639e1b] feature 1 1 file changed, 1 insertion(+) create mode 100644 feature1.txt

Özellik dalında bir özellik daha, yani özellik 2 oluşturacağım ve taahhüt edeceğim.

 (feature) $ vi feature2.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 2' [feature 0f4db49] feature 2 1 file changed, 1 insertion(+) create mode 100644 feature2.txt

Şimdi, özellik dalının günlüğünü kontrol ederseniz, yukarıda yürüttüğüm iki yeni taahhüt var.

 (feature) $ git log --oneline 0f4db49 (HEAD -> feature) feature 2 c639e1b feature 1 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test

Şimdi bu iki yeni özelliği master dala eklemek istiyorum. Bunun için rebase komutunu kullanacağım. Özellik dalından ana dala karşı yeniden temel alacağım. Bunun yapacağı şey, özellik dalımı en son değişikliklere karşı yeniden sabitlemesidir.

 (feature) $ git rebase master Successfully rebased and updated refs/heads/feature.

Şimdi devam edeceğim ve ana şubeyi kontrol edeceğim.

 (feature) $ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits)

Ve son olarak, ana dalı benim özellik dalıma göre yeniden düzenleyin. Bu, özellik dalımdaki bu iki yeni taahhüdü alacak ve bunları ana dalımın üstünde tekrar oynatacak.

 (master) $ git rebase feature Successfully rebased and updated refs/heads/master.

Şimdi ana daldaki günlüğü kontrol edersem, özellikler dalımın iki taahhüdünün ana şubeme başarıyla eklendiğini görebiliyorum.

 (master) $ git log --oneline 766c996 (HEAD -> master, feature) feature 2 c036a11 feature 1 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test

Hepsi Git'teki reset, revert ve rebase komutlarıyla ilgiliydi.

Çözüm

Hepsi Git'teki reset, revert ve rebase komutlarıyla ilgiliydi. Umarım bu adım adım kılavuz yardımcı olmuştur. Artık, makalede belirtilen komutları kullanarak ihtiyaca göre taahhütlerinizle nasıl oynayacağınızı biliyorsunuz.