Saya pikir masalah dasar Anda di sini adalah bahwa Anda salah menafsirkan dan / atau salah memahami apa yang dilakukan git dan mengapa git melakukannya.
Saat Anda mengkloning beberapa repositori lain, git membuat salinan apa pun yang ada "di sana". Ia juga mengambil label cabang "mereka", seperti master
, dan membuat salinan dari label itu yang "nama lengkapnya" di pohon git Anda adalah (biasanya) remotes/origin/master
(tetapi dalam kasus Anda, remotes/upstream/master
). Seringkali Anda juga bisa menghilangkan remotes/
bagian tersebut, jadi Anda bisa merujuk ke salinan aslinya sebagai upstream/master
.
Jika sekarang Anda membuat dan melakukan beberapa perubahan ke beberapa file, Anda adalah satu-satunya yang memiliki perubahan tersebut. Sementara itu, orang lain dapat menggunakan repositori asli (tempat Anda membuat klon) untuk membuat klon lain dan mengubah klon tersebut. Mereka adalah satu-satunya yang memiliki perubahan, tentunya. Namun pada akhirnya, seseorang mungkin memiliki perubahan yang mereka kirim kembali ke pemilik aslinya (melalui "push" atau tambalan atau apa pun).
The git pull
perintah kebanyakan hanya singkatan untuk git fetch
diikuti oleh git merge
. Ini penting karena artinya Anda perlu memahami apa yang sebenarnya dilakukan oleh kedua operasi tersebut.
The git fetch
perintah mengatakan untuk kembali ke mana pun Anda kloning dari (atau telah ditetapkan sebagai tempat untuk mengambil dari) dan menemukan "baru barang-barang orang lain ditambahkan atau diubah atau dihapus". Perubahan tersebut disalin dan diterapkan ke salinan Anda dari apa yang Anda dapatkan dari mereka sebelumnya . Mereka tidak diterapkan pada pekerjaan Anda sendiri, hanya pada pekerjaan mereka.
The git merge
perintah lebih rumit dan adalah di mana Anda akan kacau. Apa yang dilakukannya, sedikit disederhanakan, adalah membandingkan "apa yang Anda ubah dalam salinan Anda" dengan "perubahan yang Anda ambil dari orang lain dan dengan demikian ditambahkan ke salinan-karya-karya-orang lain". Jika perubahan Anda dan perubahannya tidak menimbulkan konflik, merge
operasi menggabungkannya dan memberi Anda "komit gabungan" yang mengikat pengembangan Anda dan perkembangannya bersama-sama (meskipun ada kasus "mudah" yang sangat umum di mana Anda tidak memiliki berubah dan Anda mendapatkan "maju cepat").
Situasi yang Anda hadapi sekarang adalah situasi di mana Anda telah membuat perubahan dan melakukannya — sembilan kali, pada kenyataannya, karena itu "9 di depan" —dan mereka tidak membuat perubahan. Jadi, dengan fetch
patuh tidak mengambil apa-apa, dan kemudian merge
mengambil kekurangan-perubahan mereka dan juga tidak melakukan apa-apa.
Yang Anda inginkan adalah melihat, atau mungkin bahkan "menyetel ulang" ke, versi kode "mereka".
Jika Anda hanya ingin melihatnya, Anda dapat melihat versi itu:
git checkout upstream/master
Itu memberitahu git bahwa Anda ingin memindahkan direktori saat ini ke cabang yang nama lengkapnya sebenarnya remotes/upstream/master
. Anda akan melihat kode mereka sejak terakhir kali Anda menjalankan git fetch
dan mendapatkan kode terbaru mereka.
Jika Anda ingin mengabaikan semua perubahan Anda sendiri, yang perlu Anda lakukan adalah mengubah gagasan git tentang revisi label mana master
, yang harus diberi nama. Saat ini, ini memberi nama komit terbaru Anda. Jika Anda kembali ke cabang itu:
git checkout master
maka git reset
perintah tersebut akan memungkinkan Anda untuk "memindahkan label", sebagaimana mestinya. Satu-satunya masalah yang tersisa (dengan asumsi Anda benar-benar siap untuk meninggalkan semua yang telah Anda lakukan) adalah menemukan di mana label harus menunjuk.
git log
akan membiarkan Anda menemukan nama numerik — hal-hal seperti 7cfcb29
—yang merupakan nama permanen (tidak pernah berubah), dan ada banyak cara lain untuk menamainya, tetapi dalam hal ini Anda hanya menginginkan namanya upstream/master
.
Untuk memindahkan label, memusnahkan perubahan Anda sendiri (apapun yang Anda telah berkomitmen sebenarnya dipulihkan untuk cukup lama tapi itu jauh lebih sulit setelah ini jadi sangat yakin):
git reset --hard upstream/master
Perintah itu --hard
memberitahu git untuk menghapus apa yang telah Anda lakukan, memindahkan label cabang saat ini, dan kemudian memeriksa komit yang diberikan.
Tidak terlalu umum untuk benar - benar ingin git reset --hard
dan menghapus banyak pekerjaan. Metode yang lebih aman (membuatnya jauh lebih mudah untuk memulihkan pekerjaan itu jika Anda memutuskan beberapa di antaranya bermanfaat) adalah dengan mengganti nama cabang Anda yang ada:
git branch -m master bunchofhacks
dan kemudian buat cabang lokal baru bernama master
"trek" (Saya tidak terlalu suka istilah ini karena menurut saya ini membingungkan orang, tetapi itu istilah git :-)) master asal (atau upstream):
git branch -t master upstream/master
yang kemudian dapat Anda lakukan sendiri:
git checkout master
Apa yang dilakukan tiga perintah terakhir (ada pintasan untuk menjadikannya hanya dua perintah) adalah mengubah nama yang ditempelkan pada label yang ada, lalu membuat label baru, lalu beralih ke label itu:
sebelum melakukan apapun:
C0 - "remotes/upstream/master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "master"
setelah git branch -m
:
C0 - "remotes/upstream/master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks"
setelah git branch -t master upstream/master
:
C0 - "remotes/upstream/master", "master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks"
Berikut C0
adalah komit terbaru (pohon sumber lengkap) yang Anda dapatkan saat pertama kali melakukan git clone
. C1 hingga C9 adalah komitmen Anda.
Perhatikan bahwa jika Anda menjadi git checkout bunchofhacks
dan kemudian git reset --hard HEAD^^
, ini akan mengubah gambar terakhir menjadi:
C0 - "remotes/upstream/master", "master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 - "bunchofhacks"
\
\- C8 --- C9
Alasannya adalah HEAD^^
menamai revisi dua dari kepala cabang saat ini (yang tepat sebelum reset akan dilakukan bunchofhacks
), dan reset --hard
kemudian memindahkan label. Commits C8 dan C9 sekarang sebagian besar tidak terlihat (Anda dapat menggunakan hal-hal seperti reflog dan git fsck
menemukannya tetapi tidak lagi sepele). Label Anda adalah milik Anda untuk dipindahkan sesuka Anda. The fetch
perintah mengurus orang-orang yang memulai dengan remotes/
. Adalah konvensional untuk mencocokkan "milik Anda" dengan "milik mereka" (jadi jika mereka memiliki remotes/origin/mauve
Anda akan menamai Anda mauve
juga), tetapi Anda dapat mengetikkan "milik mereka" kapan pun Anda ingin memberi nama / melihat komitmen yang Anda dapatkan "dari mereka". (Ingatlah bahwa "satu komit" adalah keseluruhan pohon sumber. Anda dapat memilih satu file tertentu dari satu komit, dengan git show
misalnya,