Reset cabang repositori lokal menjadi seperti HEAD repositori jarak jauh

3858

Bagaimana cara mereset cabang lokal saya menjadi seperti cabang pada repositori jarak jauh?

Aku melakukannya:

git reset --hard HEAD

Tapi ketika saya menjalankan git status,

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
      modified:   java/com/mycompany/TestContacts.java
      modified:   java/com/mycompany/TestParser.java

Bisakah Anda memberi tahu saya mengapa saya memiliki ini 'dimodifikasi'? Saya belum menyentuh file-file ini? Jika saya melakukannya, saya ingin menghapusnya.

hap497
sumber
8
Menurut output dari git statusperintah kedua Anda git reset --hard HEADgagal. Anda tidak menempelkan hasilnya. → Pertanyaan tidak lengkap.
Robert Siemer
2
Anda mencampurkan dua masalah di sini: 1) cara mengatur ulang cabang lokal ke titik di mana remote berada dan 2) cara menghapus area pementasan Anda (dan mungkin direktori kerja), demikian git statusbunyinya nothing to commit, working directory clean. - Silakan tentukan!
Robert Siemer

Jawaban:

6699

Mengatur cabang Anda agar sama persis dengan cabang jarak jauh dapat dilakukan dalam dua langkah:

git fetch origin
git reset --hard origin/master

Jika Anda ingin menyimpan status cabang saat ini sebelum melakukan ini (untuk berjaga-jaga), Anda dapat melakukan:

git commit -a -m "Saving my work, just in case"
git branch my-saved-work

Sekarang pekerjaan Anda disimpan di cabang "my-save-work" jika Anda memutuskan ingin kembali (atau ingin melihatnya nanti atau membandingkannya dengan cabang yang diperbarui).

Perhatikan bahwa contoh pertama mengasumsikan bahwa nama repo jarak jauh adalah "asal" dan bahwa cabang bernama "master" di repo jarak jauh cocok dengan cabang yang saat ini check-out di repo lokal Anda.

BTW, situasi di mana Anda berada terlihat sangat buruk seperti kasus umum di mana dorongan telah dilakukan ke cabang repositori non-telanjang saat ini diperiksa. Apakah Anda baru saja mendorong repo lokal Anda? Jika tidak, maka jangan khawatir - sesuatu yang lain pasti menyebabkan file-file ini tiba-tiba berubah. Jika tidak, Anda harus menyadari bahwa tidak disarankan untuk mendorong ke repositori yang tidak kosong (dan tidak ke cabang yang saat ini telah ditutup, khususnya).

Dan Moulding
sumber
4
Terima kasih atas jawaban Anda. Anda mengatakan 'Perhatikan bahwa contoh pertama mengasumsikan bahwa nama repo jarak jauh adalah "asal" dan bahwa cabang bernama "master" di repo jarak jauh cocok dengan cabang di repo lokal Anda.' Bagaimana saya bisa mengecek nama repo jarak jauh saya dan nama cabang saya untuk memastikan sebelum saya menjalankan 'git reset --hard'? Terima kasih lagi.
hap497
21
Jika Anda tidak secara eksplisit memberi nama remote, maka nama itu kemungkinan hanya "asal" (default). Anda dapat menggunakan "git remote" untuk mendapatkan daftar semua nama jarak jauh. Anda kemudian dapat menggunakan "git remote <name>" untuk melihat cabang mana yang mendorong / menarik satu sama lain (mis. Jika cabang "master" Anda dikloning dari "master" di remote yang bernama "asal", maka Anda akan mendapatkan garis yang mengatakan "master bergabung dengan master jarak jauh").
Dan Moulding
6
"tidak disarankan untuk mendorong ke repositori non-telanjang (dan tidak ke cabang yang saat ini check-out, khususnya" Mengapa begitu?
LeeGee
27
Hanya setelah mengambil, saya yakin Anda bisa melakukannya git reset FETCH_HEAD --hard, juga, itu artinya sama.
Jean
6
Itu tidak menghapus file yang saya tambahkan.
Trismegistos
417

Saya perlu melakukan (solusi dalam jawaban yang diterima):

git fetch origin
git reset --hard origin/master

Diikuti oleh:

git clean -f

untuk menghapus file lokal

Untuk melihat file apa yang akan dihapus (tanpa benar-benar menghapusnya):

git clean -n -f
Akavall
sumber
89
juga, git clean -d -fjika ada direktori terlacak hadir.
garg
54
jugagit clean -fdx
Swapnil Kotwal
14
Jika Anda ingin salinan persis cabang jarak jauh Anda harus mengikuti dengan git clean -ffdx Perhatikan bahwa ada dua f.
Trismegistos
6
Itu git clean -fadalah bagian penting yang saya butuhkan. Terima kasih!
Lakukan
17
hati-hati menggunakan perintah bersih. itu dapat menghapus file yang diabaikan dari cabang lain.
mikoop
307

Pertama, setel ulang ke HEADcabang hulu yang diambil sebelumnya :

git reset --hard @{u}

Keuntungan dari menentukan @{u}atau bentuk verbose-nya @{upstream}adalah bahwa nama repo dan cabang jarak jauh tidak harus secara eksplisit ditentukan.

Selanjutnya, sesuai kebutuhan, hapus file yang tidak terlacak, secara opsional juga dengan -x:

git clean -df

Akhirnya, sesuai kebutuhan, dapatkan perubahan terbaru:

git pull
Acumenus
sumber
54
Ini sepertinya jawaban yang lebih baik daripada yang diterima, karena secara dinamis me-reset ke cabang hulu saat ini daripada selalu yang statis sepertiorigin/master
Jon z
@Jonz spot on, @{upstream}sangat berguna dan dapat digunakan dalam alias:alias resetthisbranch="git reset --hard @{upstream}"
Siddhartha
1
@ GangadharJannu git reset --hardmemerlukan komit, kalau tidak, tidak akan tahu harus mengatur ulang apa. @{u}menunjuk ke komit tertentu - kepala cabang yang dilacak, sejak terakhir kali Anda melakukan a git fetch.
Kristoffer Bakkejord
1
@KristofferBakkejord Terima kasih atas penjelasannya tetapi bahkan tanpa melakukan hash kita dapat melakukannya git reset --hardmeskipun tidak akan diatur ulang ke cabang jauh
Gangadhar JANNU
3
Untuk siapa pun yang hampir membuka pertanyaan baru di sini, jika Anda git dari Powershell, gunakan tanda kutip ( git reset --hard "@{u}"). Butuh waktu beberapa saat untuk memikirkannya.
MPStoering
112

git reset --hard HEADsebenarnya hanya me-reset ke kondisi komitmen terakhir. Dalam hal ini KEPALA mengacu pada KEPALA cabang Anda.

Jika Anda memiliki beberapa komitmen, ini tidak akan berhasil ..

Apa yang mungkin ingin Anda lakukan, adalah mengatur ulang ke kepala asal atau apa pun yang Anda sebut repositori jarak jauh. Saya mungkin hanya akan melakukan sesuatu seperti

git reset --hard origin/HEAD

Berhati-hatilah. Reset keras tidak mudah dibatalkan. Lebih baik dilakukan seperti yang disarankan Dan, dan cabut salinan perubahan Anda sebelum mengatur ulang.

Mikael Ohlson
sumber
2
Ada saran yang salah dalam jawaban saya yang ditangkap Dan sebelumnya. Saya mengeditnya, karena saya tidak ingin menyesatkan siapa pun. Mengenai hal asal / master atau asal / hal-hal KEPALA, saya berharap itu tergantung pada apakah Anda benar-benar melakukan pengambilan terlebih dahulu. Jika Anda baru saja mengkloning asal, dan tidak memiliki cabang lain, yang saya temukan cukup umum, maka itu harus meresetnya dengan baik. Tapi tentu saja, Dan benar.
Mikael Ohlson
73

Semua saran di atas benar, tetapi seringkali untuk benar - benar mengatur ulang proyek Anda, Anda juga perlu menghapus bahkan file yang ada di dalam Anda .gitignore.

Untuk mendapatkan persamaan moral dengan menghapus direktori proyek Anda dan kloning ulang dari jarak jauh adalah:

git fetch
git reset --hard
git clean -x -d -f

Peringatan : git clean -x -d -ftidak dapat dipulihkan dan Anda dapat kehilangan file dan data (mis. Hal-hal yang Anda abaikan menggunakan .gitignore).

Christopher Smith
sumber
12
Peringatan: "git clean -x -d -f" tidak dapat dipulihkan dan Anda dapat kehilangan file dan data di .gitignore
Akarsh Satija
Sedikit lebih pendek: git clean -xdfitu sama dengan git clean -x -d -f.
Kiryl
git clean -ffxd untuk menghapus semua yang tidak ada di repo
Trismegistos
44

Gunakan perintah di bawah ini. Perintah-perintah ini juga akan menghapus semua file yang tidak terlacak dari git lokal

git fetch origin
git reset --hard origin/master
git clean -d -f
Jamsheer
sumber
6
Ini adalah respons yang lebih lengkap karena tanpa git clean -d -fkita masih akan memiliki beberapa hal dari cabang lama di direktori lokal. Terima kasih sobat.
Flavio
3
Inilah yang SEBENARNYA membuatnya menjadi seperti remote. Bersih itu penting.
David S.
1
git clean -ffxd untuk benar-benar menghapus semuanya
Trismegistos
1
Inilah yang saya butuhkan. Terima kasih
AllJs
38

Pertanyaannya mencampur dua masalah di sini:

  1. cara mengatur ulang cabang lokal ke titik di mana remote berada
  2. cara menghapus area pementasan Anda (dan mungkin direktori kerja), sehingga git statusdikatakannothing to commit, working directory clean.

Jawabannya adalah:

  1. git fetch --prune (opsional) Memperbarui snapshot lokal repo jarak jauh. Perintah selanjutnya hanya bersifat lokal.
    git reset --hard @{upstream}Letakkan penunjuk cabang lokal ke tempat snapshot jarak jauh, serta atur indeks dan direktori kerja ke file komit itu.
  2. git clean -d --force Menghapus file dan direktori yang tidak terlacak yang menghalangi git untuk mengatakan "direktori kerja bersih".
Robert Siemer
sumber
1
The @{upstream}sintaks membutuhkan hulu menjadi set yang terjadi secara default jika Anda git checkout <branchname>. - Kalau tidak gantikan dengan origin/<branchname>.
Robert Siemer
Tambahkan -xke git cleanuntuk menghapus semua yang tidak ada dalam komit (yaitu file bahkan diabaikan dengan mekanisme .gitignore).
Robert Siemer
22

Ini adalah sesuatu yang saya hadapi secara teratur, & Saya telah menyamaratakan naskah yang disediakan Wolfgang di atas untuk bekerja dengan cabang mana pun

Saya juga menambahkan prompt "Apakah Anda yakin", & beberapa output umpan balik

#!/bin/bash
# reset the current repository
# WF 2012-10-15
# AT 2012-11-09
# see http://stackoverflow.com/questions/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
branchname=`git rev-parse --symbolic-full-name --abbrev-ref HEAD`
read -p "Reset branch $branchname to origin (y/n)? "
[ "$REPLY" != "y" ] || 
echo "about to auto-commit any changes"
git commit -a -m "auto commit at $timestamp"
if [ $? -eq 0 ]
then
  echo "Creating backup auto-save branch: auto-save-$branchname-at-$timestamp"
  git branch "auto-save-$branchname-at-$timestamp" 
fi
echo "now resetting to origin/$branchname"
git fetch origin
git reset --hard origin/$branchname
Andrew Tulloch
sumber
3
Anda mungkin ingin menggunakan "git remote" untuk mendapatkan nama remote. Dalam kasus tertentu, itu bukan "asal"
Yurik
17

Asalkan repositori jarak jauh itu origin, dan Anda tertarik pada branch_name:

git fetch origin
git reset --hard origin/<branch_name>

Anda juga harus mereset cabang originke saat ini HEAD.

git fetch origin
git reset --hard origin/HEAD

Bagaimana itu bekerja:

git fetch origin mengunduh yang terbaru dari jarak jauh tanpa mencoba menggabungkan atau mengubah apa pun.

Kemudian git resetreset <branch_name>cabang ke apa yang baru saja Anda ambil. The --hardpilihan perubahan semua file dalam pohon kerja Anda untuk mencocokkan file dalam origin/branch_name.

eigenharsha
sumber
14

Aku melakukannya:

git branch -D master
git checkout master

untuk benar-benar mereset cabang


perhatikan, Anda harus checkout ke cabang lain untuk dapat menghapus cabang yang diperlukan

pengguna2846569
sumber
5
Anda harus membaca pertanyaan sekali lagi, tidak ada yang mempengaruhi remote, tetapi pengaturannya sama dengan remote, jadi Anda tidak boleh melakukan apa pun dengan remote, dan ini membantu dalam kasus saya dan bukan di atas.
user2846569
Jika Anda ingin mengaturnya menjadi sama dengan remote, Anda setidaknya harus melakukan pengambilan di beberapa titik, tidakkah Anda setuju?
Tim
2
Anda setidaknya harus mencoba ini atau membaca dokumen: kernel.org/pub/software/scm/git/docs/git-checkout.html
user2846569
Cara untuk pergi, saya punya file .pck korup di cabang dan pilihan lainnya tidak berfungsi, terima kasih !!
LuckyBrain
14

Berikut ini adalah skrip yang mengotomatiskan apa yang disarankan oleh jawaban paling populer ... Lihat https://stackoverflow.com/a/13308579/1497139 untuk versi yang disempurnakan yang mendukung cabang

#!/bin/bash
# reset the current repository
# WF 2012-10-15
# see /programming/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
git commit -a -m "auto commit at $timestamp"
if [ $? -eq 0 ]
then
  git branch "auto-save-at-$timestamp" 
fi
git fetch origin
git reset --hard origin/master
Wolfgang Fahl
sumber
10

Jika Anda memiliki masalah seperti saya, bahwa Anda telah melakukan beberapa perubahan, tetapi sekarang, untuk alasan apa pun Anda ingin menyingkirkannya, cara tercepat adalah menggunakan git resetseperti ini:

git reset --hard HEAD~2

Saya memiliki 2 komitmen yang tidak diperlukan, karenanya angka 2. Anda dapat mengubahnya ke jumlah komit Anda sendiri untuk diatur ulang.

Jadi, jawab pertanyaan Anda - jika Anda 5 berkomitmen lebih dulu dari HEAD repositori jarak jauh, Anda harus menjalankan perintah ini:

git reset --hard HEAD~5

Perhatikan bahwa Anda akan kehilangan perubahan yang Anda buat, jadi berhati-hatilah!

Karol
sumber
7

Jawaban sebelumnya berasumsi bahwa cabang yang akan disetel ulang adalah cabang saat ini (dicentang). Dalam komentar, OP hap497 mengklarifikasi bahwa cabang memang diperiksa, tetapi ini tidak secara eksplisit diperlukan oleh pertanyaan awal. Karena setidaknya ada satu pertanyaan "duplikat", Reset cabang sepenuhnya ke keadaan repositori , yang tidak menganggap bahwa cabang dicentang, inilah alternatifnya:

Jika cabang "mybranch" saat ini tidak dicentang, untuk mengatur ulang ke cabang "myremote / mybranch" cabang jauh, Anda dapat menggunakan perintah tingkat rendah ini :

git update-ref refs/heads/mybranch myremote/mybranch

Metode ini membiarkan cabang yang diperiksa keluar, dan pohon yang bekerja tidak tersentuh. Itu hanya memindahkan kepala mybranch ke komitmen lain, apa pun yang diberikan sebagai argumen kedua. Ini sangat membantu jika beberapa cabang perlu diperbarui ke head jarak jauh yang baru.

Namun, berhati-hatilah saat melakukan ini, dan gunakan gitkatau alat serupa untuk mengecek sumber dan tujuan. Jika Anda secara tidak sengaja melakukan ini pada cabang saat ini (dan git tidak akan menghindarkan Anda dari hal ini), Anda mungkin menjadi bingung, karena konten cabang yang baru tidak cocok dengan pohon kerja, yang tidak berubah (untuk memperbaiki, perbarui cabang lagi, ke tempat sebelumnya).

Rainer Blome
sumber
7

Inilah yang sering saya gunakan:

git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force;

Perhatikan bahwa itu adalah praktik yang baik untuk tidak membuat perubahan untuk menguasai lokal / mengembangkan cabang, melainkan checkout ke cabang lain untuk perubahan, dengan nama cabang prepended dengan jenis perubahan, misalnya feat/, chore/, fix/, dll Jadi Anda hanya perlu tarik perubahan, jangan mendorong perubahan apa pun dari master. Hal yang sama untuk cabang lain yang berkontribusi bagi orang lain. Jadi hal di atas hanya boleh digunakan jika Anda telah melakukan perubahan pada cabang yang telah dilakukan orang lain, dan perlu diatur ulang. Kalau tidak di masa depan hindari mendorong ke cabang yang mendorong orang lain, sebaliknya checkout dan mendorong ke cabang tersebut melalui cabang keluar.

Jika Anda ingin mengatur ulang cabang lokal Anda ke komit terbaru di cabang hulu, sejauh ini yang berfungsi untuk saya adalah:

Periksa remote Anda, pastikan hulu dan asal Anda sesuai dengan yang Anda harapkan, jika tidak seperti yang diharapkan git remote add upstream <insert URL>, gunakan , mis. Repo GitHub asli yang Anda gunakan , dan / atau git remote add origin <insert URL of the forked GitHub repo>.

git remote --verbose

git checkout develop;
git commit -m "Saving work.";
git branch saved-work;
git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force

Di GitHub, Anda juga dapat checkout cabang dengan nama yang sama dengan yang lokal, untuk menyimpan pekerjaan di sana, meskipun ini tidak perlu jika asal berkembang memiliki perubahan yang sama dengan cabang disimpan-kerja lokal. Saya menggunakan cabang berkembang sebagai contoh, tetapi bisa berupa nama cabang yang ada.

git add .
git commit -m "Reset to upstream/develop"
git push --force origin develop

Kemudian jika Anda perlu menggabungkan perubahan ini dengan cabang lain sementara di mana ada konflik, menjaga perubahan dalam pengembangan, gunakan:

git merge -s recursive -X theirs develop

Saat digunakan

git merge -s recursive -X ours develop

untuk mempertahankan perubahan yang bertentangan branch_name. Kalau tidak gunakan mergetool dengangit mergetool .

Dengan semua perubahan bersama:

git commit -m "Saving work.";
git branch saved-work;
git checkout develop;
git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force;
git add .;
git commit -m "Reset to upstream/develop";
git push --force origin develop;
git checkout branch_name;
git merge develop;

Perhatikan bahwa alih-alih hulu / pengembangan Anda dapat menggunakan hash komit, nama cabang lain, dll. Gunakan alat CLI seperti Oh My Zsh untuk memeriksa bahwa cabang Anda berwarna hijau yang menunjukkan bahwa tidak ada yang perlu dikomit dan direktori kerja bersih ( yang dikonfirmasi atau juga dapat diverifikasi oleh git status). Perhatikan bahwa ini sebenarnya dapat menambahkan komit dibandingkan dengan pengembangan hulu jika ada sesuatu yang secara otomatis ditambahkan oleh komit, misalnya diagram UML, header lisensi, dll., Jadi dalam hal ini, Anda kemudian dapat menarik perubahan origin developke upstream develop, jika diperlukan.

James Ray
sumber
6

Jawabannya

git clean -d -f

diremehkan ( -d untuk menghapus direktori). Terima kasih!

Anael
sumber
Dan untuk folder repo bersih penuh, 100% tanpa file tambahan, jalankan git clean -xdf. Ini akan menghapus semua dan semua file yang tidak diketahui git, dan akan membuat folder Anda sama persis dengan apa yang ada dalam daftar objek git. Perhatikan bahwa Anda dapat menambahkan -n(misalnya git clean -nxdf) untuk melakukan "bagaimana-jika" dan ia akan memberi tahu Anda apa yang akan dihapus tanpa benar-benar melakukan apa pun. ( git clean )
qJake
5

Jika Anda ingin kembali ke HEADstatus untuk direktori kerja dan indeks, maka Anda harus git reset --hard HEAD, daripada melakukannya HEAD^. (Ini mungkin salah ketik, sama seperti dasbor tunggal versus ganda --hard.)

Adapun pertanyaan spesifik Anda tentang mengapa file-file itu muncul dalam status sebagai diubah, sepertinya Anda melakukan soft reset alih-alih hard reset. Ini akan menyebabkan file yang diubah di HEADkomit muncul seolah-olah mereka dipentaskan, yang kemungkinan Anda lihat di sini.

Emil Sit
sumber
4

Tidak ada jumlah reset dan pembersihan tampaknya memiliki efek pada file yang tidak terlacak dan dimodifikasi dalam repo git lokal saya (saya mencoba semua opsi di atas). Satu-satunya solusi saya untuk ini adalah dengan repo lokal dan mengkloningnya dari jarak jauh.

Untungnya saya tidak memiliki cabang lain yang saya pedulikan.

xkcd: Git

Martin
sumber
1

Satu-satunya solusi yang berfungsi dalam semua kasus yang saya lihat adalah menghapus dan membatalkan. Mungkin ada cara lain, tapi jelas dengan cara ini tidak ada kemungkinan keadaan lama ditinggalkan di sana, jadi saya lebih suka itu. Bash one-liner yang bisa Anda atur sebagai makro jika Anda sering mengacaukan segalanya di git:

REPO_PATH=$(pwd) && GIT_URL=$(git config --get remote.origin.url) && cd .. && rm -rf $REPO_PATH && git clone --recursive $GIT_URL $REPO_PATH && cd $REPO_PATH

* menganggap file .git Anda tidak rusak

sudo
sumber
4
Anda juga dapat menginstal ulang sistem operasi Anda jika Anda ingin memastikannya!
Sebastian Scholle
1

Apakah Anda lupa membuat cabang fitur dan telah melakukan kesalahan langsung pada master?

Anda dapat membuat cabang fitur sekarang dan mengatur master kembali tanpa mempengaruhi worktree (sistem file lokal) untuk menghindari memicu build, tes, dan masalah dengan kunci file:

git checkout -b feature-branch
git branch -f master origin/master
Grastveit
sumber
1

Hanya 3 perintah yang akan membuatnya bekerja

git fetch origin
git reset --hard origin/HEAD
git clean -f
Deep Nirmal
sumber
-3

Jika Anda tidak keberatan menyimpan perubahan lokal, namun masih ingin memperbarui repositori agar sesuai dengan asal / KEPALA, Anda dapat menyimpan simpanan perubahan lokal Anda dan kemudian menarik:

git stash
git pull
Micah Walter
sumber