Perbedaan antara git pull dan git pull --rebase

311

Saya mulai menggunakan git di masa lalu dan tidak sepenuhnya memahami seluk-beluknya. Pertanyaan dasar saya di sini adalah untuk mengetahui perbedaan antara a git pulldan git pull --rebase, karena menambahkan --rebaseopsi tampaknya tidak melakukan sesuatu yang sangat berbeda: hanya melakukan tarikan.

Tolong bantu saya dengan memahami perbedaannya.

Rndm
sumber
3
Kemungkinan duplikasi git pull VS git, ambil git rebase
TJ
Tautan yang berguna
Taras Melnyk

Jawaban:

326

git pull= git fetch+ git mergeterhadap pelacakan cabang hulu

git pull --rebase= git fetch+ git rebaseterhadap pelacakan cabang hulu

Jika Anda ingin tahu bagaimana git mergedan git rebaseberbeda, baca ini .

mvp
sumber
12
Perlu dicatat bahwa perkataan git pull --rebaseitu sama dengan git fetchdan git rebasepada dasarnya seperti itu, tetapi tidak persis sama secara semantik. Ada beberapa perbedaan, beberapa di antaranya dijelaskan di sini. gitolite.com/git-pull--rebase
w0rp
8
Saya menyebutnya "kebohongan yang nyaman," untuk meminjam ungkapan dari Scott Meyers. Ini adalah cara yang baik untuk menjelaskannya.
w0rp
Sangat singkat. Saya tidak mengerti perbedaannya. Apa yang begitu penting fetch?
Hijau
240

Kadang-kadang kita memiliki hulu yang rebased / rewound cabang tempat kita bergantung. Ini bisa menjadi masalah besar - menyebabkan konflik berantakan bagi kami jika kami hilir.

Keajaiban itu git pull --rebase

Tarikan git normal, secara longgar, adalah sesuatu seperti ini (kita akan menggunakan asal yang disebut remote dan cabang bernama foo dalam semua contoh ini):

# assume current checked out branch is "foo"
git fetch origin
git merge origin/foo

Pada pandangan pertama, Anda mungkin berpikir bahwa git pull --rebase melakukan ini:

git fetch origin
git rebase origin/foo

Tapi itu tidak akan membantu jika rebase hulu melibatkan "squashing" (artinya patch-id dari komit berubah, tidak hanya pesanan mereka).

Yang berarti git pull --rebase harus melakukan sedikit lebih dari itu. Inilah penjelasan tentang apa yang dilakukannya dan bagaimana caranya.

Katakanlah titik awal Anda adalah ini:

a---b---c---d---e  (origin/foo) (also your local "foo")

Waktu berlalu, dan Anda telah membuat beberapa komitmen di atas "foo" Anda sendiri:

a---b---c---d---e---p---q---r (foo)

Sementara itu, dalam kemarahan anti-sosial, pengelola hulu tidak hanya mengubah "foo" -nya, ia bahkan menggunakan satu atau dua squash. Rantai komitnya sekarang terlihat seperti ini:

a---b+c---d+e---f  (origin/foo)

Git pull pada titik ini akan menghasilkan kekacauan. Bahkan git mengambil; git rebase origin / foo tidak akan memotongnya, karena melakukan "b" dan "c" di satu sisi, dan melakukan "b + c" di sisi lain, akan konflik. (Dan juga dengan d, e, dan d + e).

Apa yang git pull --rebasedilakukan, dalam hal ini, adalah:

git fetch origin
git rebase --onto origin/foo e foo

Ini memberi Anda:

 a---b+c---d+e---f---p'---q'---r' (foo)

Anda mungkin masih mendapatkan konflik, tetapi itu akan menjadi konflik asli (antara p / q / r dan a / b + c / d + e / f), dan bukan konflik yang disebabkan oleh b / c yang bertentangan dengan b + c, dll.

Jawaban diambil dari (dan sedikit dimodifikasi):
http://gitolite.com/git-pull--rebase

Mauri Lopez
sumber
9
Ini jawaban terbaik. Anda mungkin ingin mengubah hasil akhir a---b+c---d+e---f---p'---q'---r' (foo)sejak rebase mengubah hash.
Bastien
22
Jawaban ini disalin dan ditempel kata demi kata dari gitolite.com/git-pull--rebase dan harus menyertakan atribusi per lisensi pada halaman itu.
Wildcard
Ini penjelasan yang bagus. Tapi saya punya situasi, di mana saya berkomitmen A, dan saya mengirim PR ke repo hulu yang diterima. Kemudian ketika saya melakukan git pull --rebaseterhadap repo hulu, saya tidak mendapatkan A'komit baru di atas repo hulu yang ditarik. Bahkan tidak A'ada sama sekali. Apakah ini karena Adigabungkan ke dalam sistem? Atau apakah itu karena tidak ada perbedaan antara versi hulu dan versi saya yang diubah?
CMCDragonkai
Saya saat ini sedang membaca tutorial Git dan menggunakan respons ini untuk lebih memahami a git pull --rebase. Tetapi satu hal yang membingungkan saya dalam situasi hipotetis ini adalah bahwa pengelola hulu telah mengubah sejarah proyek yang telah ditarik ke dalam repositori pengembang lokal. Bukankah ini hanya praktik buruk pada umumnya? Jika ia ingin memecah komit / penulisan ulang sejarah, itu harus dilakukan sebelum mengintegrasikannya ke dalam repositori pusat untuk menghindari jenis konflik ini.
bmcentee148
44

Misalkan Anda memiliki dua komitmen di cabang lokal:

      D---E master
     /
A---B---C---F origin/master

Setelah "git pull", akan:

      D--------E  
     /          \
A---B---C---F----G   master, origin/master

Setelah "git pull --rebase", tidak akan ada titik gabungan G. Perhatikan bahwa D dan E menjadi komit yang berbeda:

A---B---C---F---D'---E'   master, origin/master
Deqing
sumber
1
bukankah A --- B --- C --- D '--- E' - F?
prgmrDev
5
@prgmrDev Mengapa D dan E dimasukkan sebelum F?
Jon
1
Bukankah itu tepatnya apa git rebase? Tapi kita bicarakan git pull --rebase. Dan mereka adalah hal yang berbeda.
Hijau
10

Dalam kasus yang paling sederhana tanpa tabrakan

  • with rebase: rebases komit lokal Anda di atas HEAD jarak jauh dan tidak membuat komit gabungan
  • tanpa / normal: menggabungkan dan membuat komit gabungan

Lihat juga:

man git-pull

Lebih tepatnya, git pull menjalankan git fetch dengan parameter yang diberikan dan memanggil git merge untuk menggabungkan kepala cabang yang diambil ke cabang saat ini. Dengan --rebase, ia menjalankan git rebase bukannya git merge.

Lihat juga:
Kapan saya harus menggunakan git pull --rebase?
http://git-scm.com/book/en/Git-Branching-Rebasing

drahnr
sumber
3
Dan dalam kasus tabrakan?
Rndm
1
Anda akan diminta untuk menyelesaikannya secara manual dan kemudian - lanjutkan dengan rebase: git sdd modified-file; git rebase --continueatau gabung: di git add modified-file; git commit;mana modified-filefile lokal Anda diubah secara manual / mergetool
drahnr
Apa yang istimewa tentang ini fetch? Mengapa mereka menciptakan dua rebasealiran? 1) git rebasedan 2) git pull --rebase?
Hijau
7

Untuk ini penting untuk memahami perbedaan antara Gabung dan Rebase.

Rebases adalah bagaimana perubahan harus lulus dari puncak hierarki ke bawah dan penggabungan adalah bagaimana mereka mengalir kembali ke atas.

Untuk detail, lihat - http://www.derekgourlay.com/archives/428

Sagar Mody
sumber
Saya pikir jawaban Anda menawarkan penjelasan yang jauh lebih sederhana yang tidak jelas pada sisa jawaban di atas. Terima kasih.
Aaron C