Apakah ada opsi git-merge --dry-run?

725

Saya bergabung di cabang terpencil yang mungkin memiliki banyak konflik. Bagaimana saya bisa tahu apakah akan ada konflik atau tidak?

Saya tidak melihat sesuatu seperti --dry-runon git-merge.

Otto
sumber
5
Karena percabangan murah dengan Git, mengapa tidak melakukan checkout salinan dan kemudian Anda tidak perlu melakukan dry run? Anda bisa membuang salinannya sesudahnya.
Alexander Mills

Jawaban:

812

Seperti disebutkan sebelumnya, berikan --no-commitflag, tetapi untuk menghindari fast-forward commit, ikut juga --no-ff, seperti:

$ git merge --no-commit --no-ff $BRANCH

Untuk memeriksa perubahan bertahap:

$ git diff --cached

Dan Anda bisa membatalkan penggabungan, bahkan jika itu adalah penggabungan maju-cepat:

$ git merge --abort
mipadi
sumber
51
Ini bagus, tetapi masih akan mengubah copy pekerjaan Anda. Jika repo Anda adalah server web langsung, maka Anda bisa menyajikan file dengan konflik di.
dave1010
21
Anda tidak bisa benar-benar melakukan penggabungan tanpa memengaruhi copy pekerjaan.
mipadi
55
Benar, tetapi sesuatu seperti git merge --only-if-there-wont-be-any-conflictsatau git diff --show-conflicts <commit>akan sangat berguna. Malu itu belum mungkin, atau apakah saya kehilangan sesuatu?
dave1010
344
@ dave1010 Anda seharusnya tidak pernah menangani penggabungan pada server web langsung !!! Untuk itulah kotak pengembangan Anda! Perbaiki cabang "prod" dan kemudian dorong ke server web nyata.
jpswain
52
Jika Anda bekerja di server langsung / produksi, Anda tidak ingin melakukan apa pun kecuali git pull --ff-only!
ThiefMaster
237

Saya hanya perlu mengimplementasikan metode yang secara otomatis menemukan konflik antara repositori dan remote-nya. Solusi ini melakukan penggabungan dalam memori sehingga tidak akan menyentuh indeks, atau pohon yang berfungsi. Saya pikir ini adalah cara teraman yang mungkin Anda bisa menyelesaikan masalah ini. Begini cara kerjanya:

  1. Ambil remote ke repositori Anda. Sebagai contoh: git fetch origin master
  2. Jalankan git merge-base: git merge-base FETCH_HEAD master
  3. Jalankan git merge-tree: git merge-tree mergebase master FETCH_HEAD( mergebase adalah id heksadesimal yang digabungkan-basis dicetak pada langkah sebelumnya)

Sekarang anggaplah Anda ingin menggabungkan master jarak jauh dengan master lokal Anda, tetapi Anda bisa menggunakan cabang apa pun. git merge-treeakan menjalankan gabungan dalam memori dan mencetak hasilnya ke output standar. Grep untuk polanya <<atau >>. Atau Anda dapat mencetak output ke file dan memeriksanya. Jika Anda menemukan garis yang dimulai dengan 'diubah di keduanya' maka kemungkinan besar akan ada konflik.

akostajti
sumber
41
Jawaban ini diremehkan, IMHO, karena ini solusi bersih tanpa menyentuh copy pekerjaan atau indeks.
sschuberth
23
BTW, langkah 2 dan 3 dapat digabung menjadi satu langkah, menggunakan operator backtick dari konsol Linux, yang mengevaluasi di tempat isinya:git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
jakub.g
15
Tambahkan ke [alias] di .gitconfig: dry = "! F () {git merge-tree` git merge-base $ 2 $ 1` $ 2 $ 1;}; f "# tandai bagaimana penggabungan dev menjadi master akan berjalan: git dry dev master
Noel
8
Baris GIT favorit saya: Luar git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"biasa! +100
Rudie
4
Dalam pengujian ini, saya menemukan grepping untuk penggabungan flag 'perubahan di kedua' di mana kedua cabang memodifikasi file yang sama, bahkan jika keduanya tidak menghasilkan konflik penggabungan. Untuk mengidentifikasi hanya konflik yang sebenarnya, saya merasa perlu untuk melakukan grep untuk markup konflik yang dimulai seperti ini:, +<<<<<<< .ourjadi saya menggunakan ekspresi grep sepertigrep -q '^+<* \.our$'
Guy
55

Solusi brute force sederhana saya untuk ini adalah:

  1. Buat cabang "pra-master" (dari master tentu saja)

  2. Gabungkan semua hal yang Anda inginkan ke dalam pre-master ini.
    Kemudian Anda bisa melihat bagaimana penggabungan terjadi tanpa menyentuh master.

    • Gabungkan pre-master menjadi master ATAU
    • Gabungkan semua cabang yang dirilis wannabe menjadi master

Bagaimanapun, saya akan mengikuti saran @ orange80.

neraka
sumber
5
Saya suka solusi @akostajti, tapi ini adalah pilihan lain yang diremehkan. Sebenarnya saya lebih suka bersikap defensif dan membuat cabang temp baru (tentu saja hanya ketika saya mengharapkan konflik, kalau tidak akan menjadi berlebihan), dan jika ada yang salah, cukup hapus saja.
jakub.g
1
tidak tahu apakah ini solusi "kotor" atau tidak, tetapi itu benar-benar berhasil. Saya suka itu! (Y)
sara
3
Ini harus menjadi solusi yang diterima, imo. Cepat, mudah, aman, dapat dibalik, intuitif, dan selama tidak ada perubahan yang tidak dikomit sebelum Anda mulai, itu tidak akan memiliki efek samping.
Bob Ray
3
Solusi ini memberi tahu Anda tidak mengerti cara kerja git. Branch hanya pointer dan Anda hanya membuat pointer yang redundan. Anda memiliki firasat buruk bahwa Anda entah bagaimana bisa melukai penggabungan cabang Anda tetapi Anda tidak bisa. Anda selalu dapat melakukannya git merge --abortjika ada konflik, git reset --hard HEAD~1apakah ada gabungan atau git reset --hard origin/master. Menciptakan cabang lain memberi Anda perasaan aman, tetapi jika Anda mempelajari cara kerja git, Anda akan mengerti bahwa itu adalah ketakutan yang salah tempat. Ketika kekhawatiran tentang tidak mengubah copy pekerjaan, ini tidak menawarkan solusi.
Thibault D.
@ thibault-d Pikirkan tentang betapa rumitnya solusinya saat Anda tidak memulai dengan cabang yang bersih. git merge --no-committidak akan membatalkan penggabungan jika itu dapat diteruskan dengan cepat. git merge --aborttidak berfungsi jika digabung. Jika Anda ingin menulis ini sebagai skrip, ini aneh, karena git mergetidak membalas dengan kode kesalahan yang cukup baik untuk menjelaskan berbagai jenis konflik. Bekerja dengan cabang baru mencegah skrip rusak meninggalkan repo Anda dalam keadaan yang memerlukan intervensi manual. Tentu Anda tidak bisa kehilangan apapun. Tetapi lebih mudah untuk membangun sebaliknya.
Erik Aronesty
47

Mengurungkan penggabungan dengan git sangat mudah sehingga Anda tidak perlu khawatir tentang dry run:

$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world

SUNTING: Seperti disebutkan dalam komentar di bawah ini, jika Anda memiliki perubahan dalam direktori kerja Anda atau area pementasan Anda mungkin ingin menyimpannya sebelum melakukan hal di atas (jika tidak mereka akan menghilang mengikuti yang di git resetatas)

Brian Phillips
sumber
7
Cukup memeriksa apakah penggabungan akan maju cepat (FF) adalah masalah memeriksa daftar git branch --contains HEADatau bahkan lebih langsung, cukup gunakangit merge --ff-only
Brian Phillips
7
git reset --hard adalah salah satu dari sedikit perintah penghapusan informasi tanpa backout yang dimiliki git, jadi harus digunakan dengan sangat hati-hati. Dengan demikian, -1
Kzqai
8
@Tchalvak masih ada reflog.
Kissaki
3
--dry-runtidak akan "cukup memeriksa apakah penggabungan akan maju cepat". Itu akan mengembalikan output yang tepat bahwa penggabungan akan: file, konflik dll. Apakah akan ff tidak benar-benar menarik, bukan?
Rudie
3
bagaimana git stash; git reset --hard? @BrianPhillips
Code Whisperer
41

Saya membuat alias untuk melakukan ini dan bekerja seperti pesona, saya melakukan ini:

 git config --global alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '

Sekarang saya hanya menelepon

git mergetest <branchname>

Untuk mengetahui apakah ada konflik.

Okonomiyaki3000
sumber
Cemerlang! Saya menyimpan ini.
qbert65536
28

Hanya beda cabang Anda saat ini dengan cabang jarak jauh, ini akan memberi tahu Anda apa yang akan berubah ketika Anda melakukan tarikan / penggabungan.

#see diff between current master and remote branch
git diff master origin/master
timh
sumber
1
Ide yang menarik. Bagaimana saya melihat output itu dan menentukan apakah penggabungan akan berfungsi atau tidak?
MatrixFrog
6
Ini tidak akan memberi tahu Anda jika ada konflik akan terjadi ... tetapi itu akan memberi Anda gambaran umum tentang apa yang akan terjadi jika Anda melakukan penarikan / penggabungan.
timh
10
Ini hanya akan memberi tahu Anda perbedaan antara dua cabang, itu tidak akan memberi tahu Anda apa hasil dari penggabungan akan. Ini adalah perbedaan penting karena penggabungan akan dalam beberapa kasus secara otomatis mengambil perubahan dari cabang yang berbeda tergantung pada kapan mereka berkomitmen. Jadi pada dasarnya, melakukan diff mungkin membuat Anda berpikir beberapa perubahan Anda akan dikembalikan ketika dalam kenyataannya, proses penggabungan akan secara otomatis mengambil perubahan yang lebih baru daripada yang lebih lama. Harapan itu masuk akal.
markquezada
3
Untuk membangun komentar @ mirthlab, akan ada perbedaan yang signifikan antara diff dan penggabungan jika seseorang sebelumnya melakukan penggabungan dengan strategi penggabungan "milik kami" (atau beberapa perbaikan penggabungan manual lainnya); diff juga akan menunjukkan kepada Anda perbedaan yang sudah dihitung sebagai "digabung".
Tao
21

Saya menggunakan perintah request-pull git untuk melakukannya. Ini memungkinkan Anda untuk melihat setiap perubahan yang akan terjadi saat penggabungan, tetapi tanpa melakukan apa pun di repositori lokal atau jauh Anda .

Misalnya, bayangkan Anda ingin menggabungkan cabang bernama "fitur-x" ke cabang master Anda

git request-pull master origin feature-x

akan menunjukkan kepada Anda ringkasan tentang apa yang akan terjadi (tanpa melakukan apa pun):

The following changes since commit fc01dde318:
    Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
    http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
    Adding some layout
    Refactoring
ioserver.js            |   8 +++---
package.json           |   7 +++++-
server.js              |   4 +--
layout/ldkdsd.js       | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js

Jika Anda menambahkan -pparameter, Anda juga akan mendapatkan teks tambalan lengkap, persis seperti jika Anda melakukan git diff pada setiap file yang diubah.

ArnaudR
sumber
3
Anda bisa membuatnya lebih jelas dengan menambahkan apa masterdan originlakukan di opsi baris perintah, dan bagaimana jika saya misalnya pada lokal branch1dan ingin melakukan request-pullpada cabang fitur lokal branch2? Apakah saya masih membutuhkan origin? Tentu saja, orang selalu dapat membaca dokumentasi.
Ela782
Sayangnya perintah ini hanya berfungsi jika Rev # 2 adalah nama cabang, itu tidak bekerja untuk hash: /
Jared Grubb
20

Saya terkejut belum ada yang menyarankan untuk menggunakan tambalan.

Katakanlah Anda ingin menguji gabungan dari your_branchke master(aku asumsi Anda telah mastermemeriksa):

$ git diff master your_branch > your_branch.patch
$ git apply --check your_branch.patch
$ rm your_branch.patch

Itu harus melakukan trik.

Jika Anda mendapatkan kesalahan seperti

error: patch failed: test.txt:1
error: test.txt: patch does not apply

itu berarti bahwa tambalan tidak berhasil dan penggabungan akan menghasilkan konflik. Tidak ada output berarti patch bersih dan Anda dapat dengan mudah menggabungkan cabang


Perhatikan bahwa ini tidak akan benar - benar mengubah pohon kerja Anda (selain membuat file tambalan tentu saja, tetapi Anda dapat dengan aman menghapusnya setelah itu). Dari dokumentasi git-apply:

--check
    Instead of applying the patch, see if the patch is applicable to the
    current working tree and/or the index file and detects errors. Turns
    off "apply".

Catatan untuk siapa saja yang lebih pintar / lebih berpengalaman dengan git daripada saya: tolong beri tahu saya jika saya salah di sini dan metode ini memang menunjukkan perilaku yang berbeda dari gabungan biasa. Tampaknya aneh bahwa dalam 8+ tahun bahwa pertanyaan ini telah ada, tidak seorang pun akan menyarankan solusi yang tampaknya jelas ini.

Christoph Böhmwalder
sumber
Metode ini adalah jawaban yang diterima untuk pertanyaan ini dan ada beberapa peringatan dalam komentar seperti "git tidak dapat menggunakan strategi penggabungan 'rekursif'" dan "file tambalan memberikan kesalahan untuk file baru". Kalau tidak, sepertinya hebat.
neno
1
Cara yang lebih pendek tanpa membuat file patch sementara: git diff master your_branch | git apply --check.
ks1322
9

Ini mungkin menarik: Dari dokumentasi:

Jika Anda mencoba gabungan yang mengakibatkan konflik kompleks dan ingin memulai kembali, Anda dapat memulihkan dengan git merge --abort .

Tapi Anda juga bisa melakukannya dengan cara naif (tapi lambat):

rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)

(Catatan: Ini tidak akan berfungsi hanya mengkloning ke / tmp, Anda akan memerlukan salinan, untuk memastikan bahwa perubahan yang tidak dikomit tidak akan bertentangan).


sumber
2
Jika yang Anda butuhkan adalah palu ... :) +1
kaiser
Bersih copy dapat diperoleh dengan cp -r repository/.git /tmp/repository/.git, cd /tmp/repository, git reset --hard, git add --all, git reset --hard(untuk mengukur baik), git status(untuk memeriksa bahwa itu bersih).
ADTC
8

Saya sadar bahwa ini adalah pertanyaan lama, tetapi ini adalah pertanyaan pertama yang muncul di pencarian Google.

Git memperkenalkan opsi --ff-only saat penggabungan.

Dari: http://git-scm.com/docs/git-merge


--ff-saja

Menolak untuk menggabungkan dan keluar dengan status bukan nol kecuali KEPALA saat ini sudah mutakhir atau penggabungan dapat diselesaikan sebagai fast-forward.

Melakukan hal ini akan mencoba untuk menggabungkan dan memajukan, dan jika tidak dapat membatalkan dan meminta Anda bahwa memajukan tidak dapat dilakukan, tetapi membiarkan cabang kerja Anda tidak tersentuh. Jika itu bisa maju cepat, maka itu akan melakukan penggabungan pada cabang kerja Anda. Opsi ini juga tersedia di git pull. Dengan demikian, Anda dapat melakukan hal berikut:

git pull --ff-only origin branchA #See if you can pull down and merge branchA

git merge --ff-only branchA branchB #See if you can merge branchA into branchB
Jason McKindly
sumber
1
Itu akan melakukan penggabungan jika dapat dilakukan dengan fast forward yang bukan yang saya inginkan dalam pertanyaan awal. Saya pikir jawaban yang diterima memiliki setengah lainnya yang memperbaikinya.
Otto
Namun sungguh, git mewah meminta meniadakan kebutuhan saya untuk hal semacam ini.
Otto
2
Itu tidak benar-benar sama. Keluar dengan status tidak nol karena penggabungan tidak dapat diselesaikan karena fast-forward tidak berarti ada konflik . Itu hanya berarti sejarah telah berbeda dan komit gabungan diperlukan.
ADTC
7

Saya menggunakan git log untuk melihat apa yang telah berubah pada cabang fitur dari cabang utama

git log does_this_branch..contain_this_branch_changes

mis - untuk melihat komit apa yang ada dalam cabang fitur yang telah / belum digabungkan untuk dikuasai:

git log master..feature_branch
nelsonenzo
sumber
3

Jika Anda ingin memajukan dari B ke A, maka Anda harus memastikan bahwa git log B..A tidak menunjukkan apa-apa kepada Anda, yaitu A tidak memiliki apa pun yang tidak dimiliki B. Tetapi bahkan jika B..A memiliki sesuatu, Anda mungkin masih dapat bergabung tanpa konflik, jadi hal di atas menunjukkan dua hal: bahwa akan ada fast-forward, dan dengan demikian Anda tidak akan mendapatkan konflik.

Erik Kaplun
sumber
2

Solusi saya adalah menggabungkan kembali.

Daripada menggabungkan cabang Anda ke cabang "target" yang jauh, gabungkan cabang itu ke cabang Anda.

git checkout my-branch
git merge origin/target-branch

Anda akan melihat apakah ada konflik dan dapat merencanakan bagaimana menyelesaikannya.

Setelah itu Anda dapat membatalkan penggabungan melalui git merge --abort, atau (jika tidak ada konflik dan penggabungan telah terjadi) kembalikan ke komit sebelumnya melaluigit reset --hard HEAD~1

Ubeogesh
sumber
-2

Buat salinan sementara dari copy pekerjaan Anda, kemudian gabungkan menjadi itu, dan bedakan keduanya.

vanboom
sumber