Zresetuj gałąź repozytorium lokalnego tak, aby działała jak HEAD

3850

Jak zresetować mój oddział lokalny, aby był taki sam jak oddział w zdalnym repozytorium?

Zrobiłem:

git reset --hard HEAD

Ale kiedy uruchomić 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

Czy możesz mi powiedzieć, dlaczego mam te „zmodyfikowane”? Nie dotknąłem tych plików? Jeśli tak, chcę je usunąć.

hap497
źródło
8
Zgodnie z danymi wyjściowymi git statusdrugiego polecenia git reset --hard HEADnie powiodło się. Jednak nie wkleiłeś danych wyjściowych. → Niekompletne pytanie.
Robert Siemer
2
Mieszasz tutaj dwa problemy: 1) jak zresetować lokalną gałąź do punktu, w którym znajduje się pilot, i 2) jak wyczyścić obszar przejściowy (i ewentualnie katalog roboczy), tak git statusmówi nothing to commit, working directory clean. - Proszę sprecyzuj!
Robert Siemer

Odpowiedzi:

6685

Ustawienie gałęzi dokładnie pasującej do gałęzi zdalnej można wykonać w dwóch krokach:

git fetch origin
git reset --hard origin/master

Jeśli chcesz zapisać stan bieżącego oddziału przed zrobieniem tego (na wszelki wypadek), możesz:

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

Teraz twoja praca jest zapisywana w gałęzi „moja-zapisana-praca” na wypadek, gdybyś zdecydował, że chcesz ją odzyskać (lub chcesz przejrzeć ją później lub porównać z zaktualizowanym oddziałem).

Zauważ, że w pierwszym przykładzie założono, że nazwa zdalnego repozytorium to „origin”, a gałąź o nazwie „master” w repozytorium zdalnym odpowiada aktualnie wyewidencjonowanej gałęzi w repozytorium lokalnym.

BTW, ta sytuacja, w której się znajdujesz, wygląda okropnie jak zwykły przypadek, w którym dokonano wypychania do obecnie sprawdzanej gałęzi repozytorium, które nie jest nagie. Czy ostatnio naciskałeś na lokalne repozytorium? Jeśli nie, to nie martw się - coś innego musiało spowodować, że te pliki zostaną nieoczekiwanie zmodyfikowane. W przeciwnym razie należy pamiętać, że nie zaleca się wypychania do repozytorium, które nie jest nagie (w szczególności nie do aktualnie wyewidencjonowanego oddziału).

Dan Molding
źródło
4
Dziękuję za Twoją odpowiedź. Powiedziałeś: „Zauważ, że pierwszy przykład zakłada, że ​​nazwa zdalnego repozytorium to„ origin ”, a gałąź o nazwie„ master ”w repozytorium zdalnym pasuje do gałęzi w repozytorium lokalnym.” Jak mogę dwukrotnie sprawdzić nazwę mojego zdalnego repozytorium i nazwę mojego oddziału, aby upewnić się przed wykonaniem polecenia „git reset --hard”? Dzięki jeszcze raz.
hap497
21
Jeśli nie nadałeś nazwy pilotowi, to prawdopodobnie jest to po prostu „pochodzenie” (domyślnie). Możesz użyć „git remote”, aby uzyskać listę wszystkich zdalnych nazw. Następnie możesz użyć „git remote <nazwa>”, aby zobaczyć, które gałęzie pchają / ciągną ze sobą (np. Jeśli twoja gałąź „master” została sklonowana z „master” w zdalnej nazwie „origin”, otrzymasz linię że „master łączy się ze zdalnym master”).
Dan Molding
6
„nie zaleca się wypychania do niezabezpieczonego repozytorium (a nie do obecnie wyewidencjonowanego oddziału, w szczególności” Dlaczego?
LeeGee
27
Zaraz po pobraniu, myślę, że możesz zrobić git reset FETCH_HEAD --hardzamiast tego, to ma to samo znaczenie.
Jean
6
Nie usunęło plików, które dodałem.
Trismegistos,
416

Musiałem zrobić (rozwiązanie w zaakceptowanej odpowiedzi):

git fetch origin
git reset --hard origin/master

Śledzony przez:

git clean -f

aby usunąć lokalne pliki

Aby zobaczyć, które pliki zostaną usunięte (bez faktycznego ich usuwania):

git clean -n -f
Akavall
źródło
89
także, git clean -d -fjeśli są obecne nie śledzone katalogi.
garg
54
takżegit clean -fdx
Swapnil Kotwal
14
Jeśli chcesz dokładną kopię zdalnego oddziału, musisz wykonać git clean -ffdx. Zauważ, że są dwa f.
Trismegistos
6
To git clean -fbył niezbędny element, którego potrzebowałem. Dzięki!
dgo
17
bądź ostrożny używając polecenia clean. może usuwać zignorowane pliki z innych gałęzi.
mikoop
307

Najpierw zresetuj do poprzednio pobranego HEADodpowiedniego odgałęzienia:

git reset --hard @{u}

Zaletą określenia @{u}lub jego pełnej formy @{upstream}jest to, że nazwa zdalnego repozytorium i gałęzi nie musi być wyraźnie określona.

Następnie w razie potrzeby usuń nieśledzone pliki, opcjonalnie również z -x:

git clean -df

Wreszcie, w razie potrzeby, uzyskaj najnowsze zmiany:

git pull
Acumenus
źródło
54
Wydaje się, że jest to lepsza odpowiedź niż zaakceptowana, ponieważ dynamicznie resetuje się do bieżącego odgałęzienia, a nie zawsze do statycznego, takiego jakorigin/master
Jon z
@Jonz spot on, @{upstream}jest bardzo przydatny i może być używany w aliasach:alias resetthisbranch="git reset --hard @{upstream}"
Siddhartha,
1
@GangadharJannu git reset --hardwymaga zatwierdzenia, w przeciwnym razie nie wiedziałby, do czego zresetować. @{u}wskazuje na konkretne zatwierdzenie - szef śledzonej gałęzi, od czasu, kiedy ostatnio zrobiłeś git fetch.
Kristoffer Bakkejord
1
@KristofferBakkejord Dzięki za wyjaśnienie, ale nawet bez zatwierdzenia skrótu możemy to zrobić, git reset --hardchociaż nie zresetuje się do zdalnego oddziału
Gangadhar JANNU
3
Dla każdego, kto prawie otworzył tutaj nowe pytanie, jeśli korzystasz z Powershell, użyj cudzysłowów ( git reset --hard "@{u}"). Zajęło mi to trochę czasu, aby to zrozumieć.
MPStoering,
112

git reset --hard HEADw rzeczywistości resetuje tylko do ostatniego zatwierdzonego stanu. W takim przypadku HEAD odnosi się do HEAD twojego oddziału.

Jeśli masz kilka zatwierdzeń, to nie zadziała.

To, co prawdopodobnie chcesz zrobić, to zresetować do źródła pochodzenia lub jakkolwiek nazywane jest twoje zdalne repozytorium. Prawdopodobnie zrobiłbym coś takiego

git reset --hard origin/HEAD

Bądź jednak ostrożny. Twardych resetów nie można łatwo cofnąć. Lepiej jest postępować zgodnie z sugestiami Dana i rozgałęzić kopię zmian przed zresetowaniem.

Mikael Ohlson
źródło
2
W mojej odpowiedzi była niepoprawna sugestia, którą Dan złapał wcześniej. Zedytowałem to, ponieważ nie chcę nikogo zwieść. Jeśli chodzi o pliki źródłowe / master lub origin / HEAD, spodziewam się, że zależy to od tego, czy rzeczywiście najpierw pobierasz. Jeśli właśnie sklonowałeś pochodzenie i nie miał on żadnych innych gałęzi, które moim zdaniem są dość powszechne, to powinno zresetować je dobrze. Ale oczywiście Dan ma rację.
Mikael Ohlson
73

Wszystkie powyższe sugestie są słuszne, ale często, aby naprawdę zresetować projekt, musisz również usunąć nawet pliki, które są w twoim .gitignore.

Aby uzyskać moralny odpowiednik usunięcia katalogu projektu i ponownego klonowania ze zdalnego, należy:

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

Ostrzeżenie : git clean -x -d -fjest nieodwracalne i możesz stracić pliki i dane (np. Rzeczy, których zignorowałeś .gitignore).

Christopher Smith
źródło
12
Ostrzeżenie: „git clean -x -d -f” jest nieodwracalny i możesz
utracić
Trochę krócej: git clean -xdfto równa się git clean -x -d -f.
Kiryl
git clean -ffxd, aby usunąć wszystko, co nie znajduje się w repozytorium
Trismegistos
44

Użyj poniższych poleceń. Te polecenia usuwają również wszystkie nieśledzone pliki z lokalnego gita

git fetch origin
git reset --hard origin/master
git clean -d -f
Jamsheer
źródło
6
Jest to bardziej kompletna odpowiedź, ponieważ bez tego git clean -d -fnadal będziemy mieć pewne elementy starego oddziału w katalogu lokalnym. Dzięki stary.
Flavio
3
Właśnie to faktycznie sprawia, że ​​jest podobny do pilota. Czystość jest ważna.
David S.
1
git clean -ffxd, aby naprawdę wszystko usunąć
Trismegistos
1
Właśnie tego potrzebowałem. Dzięki
AllJs
38

Pytanie łączy tutaj dwie kwestie:

  1. jak zresetować lokalną gałąź do punktu, w którym znajduje się pilot
  2. jak wyczyścić obszar pomostowy (i ewentualnie katalog roboczy), tak git statusmówinothing to commit, working directory clean.

Jedna odpowiedź to:

  1. git fetch --prune (opcjonalnie) Aktualizuje lokalną migawkę zdalnego repozytorium. Dalsze polecenia są tylko lokalne.
    git reset --hard @{upstream}Ustawia wskaźnik gałęzi lokalnej w miejscu, w którym znajduje się migawka pilota, a także ustawia indeks i katalog roboczy na pliki tego zatwierdzenia.
  2. git clean -d --force Usuwa nieśledzone pliki i katalogi, które utrudniają gitowi powiedzenie „wyczyść katalog roboczy”.
Robert Siemer
źródło
1
@{upstream}Składnia wymaga upstream być ustawione co zdarza domyślnie jeśli ciebie git checkout <branchname>. - W przeciwnym razie zastąp go origin/<branchname>.
Robert Siemer
Dodaj, -xaby git cleanusunąć wszystko, co nie jest w zatwierdzeniu (tzn. Nawet pliki ignorowane przez mechanizm .gitignore).
Robert Siemer
22

To jest coś, z czym regularnie się spotykam i uogólniłem powyższy skrypt Wolfganga do pracy z dowolną gałęzią

Dodałem również monit „jesteś pewien” i informacje zwrotne

#!/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
źródło
3
możesz użyć polecenia „git remote”, aby uzyskać nazwę pilota. W niektórych przypadkach nie będzie to „pochodzenie”
Yurik,
17

Pod warunkiem, że zdalne repozytorium jest origini że jesteś zainteresowany branch_name:

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

Możesz także zresetować bieżącą gałąź origindo HEAD.

git fetch origin
git reset --hard origin/HEAD

Jak to działa:

git fetch origin pobiera najnowsze z pilota, bez próby scalania lub zmiany bazy danych.

Następnie git resetresetuje <branch_name>gałąź do tego, co właśnie pobrałeś. Ta --hardopcja zmienia wszystkie pliki w drzewie roboczym, aby pasowały do ​​plików w origin/branch_name.

eigenharsha
źródło
14

Zrobiłem:

git branch -D master
git checkout master

całkowicie zresetować gałąź


Uwaga: należy przejść do innego oddziału, aby móc usunąć wymagany oddział

użytkownik 2846569
źródło
5
Powinieneś przeczytać pytanie jeszcze raz, nie ma wpływu na zdalne sterowanie, ale ustawienie na takie same jak zdalne, więc nie powinieneś nic robić z pilotem, a to pomogło w moim przypadku i nie powyżej.
user2846569
Jeśli chcesz ustawić to samo co zdalne, powinieneś przynajmniej w pewnym momencie pobrać, prawda?
Tim
2
powinieneś przynajmniej spróbować tego lub przeczytać dokumenty: kernel.org/pub/software/scm/git/docs/git-checkout.html
user2846569
Nawiasem mówiąc, miałem uszkodzony plik .pck w gałęzi, a reszta opcji nie działała, dzięki !!
LuckyBrain
14

Oto skrypt automatyzujący to, co sugeruje najpopularniejsza odpowiedź ... Zobacz ulepszoną wersję obsługującą oddziały https://stackoverflow.com/a/13308579/1497139

#!/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
źródło
10

Jeśli miałeś problem jak ja, że ​​dokonałeś już pewnych zmian, ale teraz, z jakiegokolwiek powodu, chcesz się go pozbyć, najszybszym sposobem jest użycie git resettego w następujący sposób:

git reset --hard HEAD~2

Miałem 2 niepotrzebne zatwierdzenia, stąd numer 2. Możesz zmienić na własną liczbę zatwierdzeń, aby zresetować.

Odpowiadając na twoje pytanie - jeśli masz 5 zatwierdzeń przed zdalnym HEAD repozytorium, powinieneś uruchomić to polecenie:

git reset --hard HEAD~5

Zauważ, że utracisz wprowadzone zmiany, więc bądź ostrożny!

Karol
źródło
7

Poprzednie odpowiedzi zakładają, że gałąź, która ma zostać zresetowana, jest bieżącą gałęzią (wypisana). W komentarzach OP hap497 wyjaśnił, że oddział jest rzeczywiście wyewidencjonowany, ale nie jest to wyraźnie wymagane w pierwotnym pytaniu. Ponieważ jest co najmniej jedno pytanie „duplikowane”, Zresetuj gałąź całkowicie do stanu repozytorium , co nie zakłada, że ​​gałąź jest wyewidencjonowana, oto alternatywa:

Jeśli gałąź „mybranch” nie jest obecnie wyewidencjonowana, aby zresetować ją do głowy oddziału „myremote / mybranch”, możesz użyć polecenia niskiego poziomu :

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

Ta metoda pozostawia wypisaną gałąź bez zmian, a działające drzewo pozostaje nietknięte. Po prostu przesuwa głowę mojego oddziału do innego zatwierdzenia, niezależnie od tego, co podano jako drugi argument. Jest to szczególnie przydatne, gdy wiele gałęzi wymaga aktualizacji do nowych zdalnych głowic.

Zachowaj jednak ostrożność i używaj gitk lub podobnego narzędzia, aby dokładnie sprawdzić źródło i miejsce docelowe. Jeśli przypadkowo zrobisz to w bieżącej gałęzi (a git cię nie powstrzyma), możesz się pomylić, ponieważ zawartość nowej gałęzi nie pasuje do działającego drzewa, które się nie zmieniło (aby to naprawić, zaktualizuj gałąź ponownie, do miejsca, gdzie było wcześniej).

Rainer Blome
źródło
7

Z tego często korzystam:

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

Należy pamiętać, że jest to dobra praktyka, aby nie wprowadzać zmian do lokalnego master / rozwinąć gałąź, ale zamiast tego utworu do innego oddziału wszelkich zmian, z nazwą oddziału poprzedzany przez rodzaj zmian, na przykład feat/, chore/, fix/, itd. W ten sposób tylko trzeba ściągaj zmiany, a nie wypychaj żadnych zmian z mastera. To samo dotyczy innych gałęzi, do których przyczyniają się inni. Dlatego powyższego należy używać tylko wtedy, gdy zdarzyło się, że dokonałeś zmian w gałęzi, do których inni się zobowiązali i musisz je zresetować. W przeciwnym razie w przyszłości unikaj wypychania do gałęzi, do której inni pchają, zamiast realizacji transakcji i wypychania do tej gałęzi za pośrednictwem wypisanej gałęzi.

Jeśli chcesz zresetować swój oddział lokalny do najnowszego zatwierdzenia w gałęzi upstream, do tej pory działa dla mnie:

Sprawdź swoje piloty, upewnij się, że twój upstream i pochodzenie są zgodne z oczekiwaniami, jeśli nie zgodnie z oczekiwaniami, skorzystaj git remote add upstream <insert URL>np. Z oryginalnego repozytorium GitHub, z którego rozwidliłeś się i / lub 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

Na GitHub możesz również pobrać gałąź o tej samej nazwie co lokalna, aby zapisać tam pracę, chociaż nie jest to konieczne, jeśli program develop origin ma takie same zmiany jak lokalna gałąź zapisanej pracy. Korzystam z gałęzi programistycznej jako przykładu, ale może to być dowolna istniejąca nazwa gałęzi.

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

Następnie, jeśli chcesz scalić te zmiany z inną gałęzią, w której występują konflikty, zachowując zmiany w rozwoju, użyj:

git merge -s recursive -X theirs develop

Podczas użytkowania

git merge -s recursive -X ours develop

aby zachować sprzeczne zmiany w nazwie gałęzi. W przeciwnym razie użyj narzędzia do łączenia z git mergetool.

Wszystkie zmiany razem:

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;

Zauważ, że zamiast upstream / develop możesz użyć skrótu zatwierdzenia, innej nazwy oddziału itp. Użyj narzędzia CLI, takiego jak Oh My Zsh, aby sprawdzić, czy twoja gałąź jest zielona, ​​wskazując, że nie ma nic do zatwierdzenia, a katalog roboczy jest czysty ( co zostało potwierdzone lub może zostać zweryfikowane przez git status). Należy pamiętać, że może to faktycznie dodać zobowiązuje porównaniu do początkowych rozwijać, czy jest coś dodawane automatycznie przez commit np diagramy UML, nagłówki licencyjne, itd., A więc w tym przypadku, można wtedy wyciągnąć zmiany na origin developcelu upstream develop, w razie potrzeby.

James Ray
źródło
6

Odpowiedź

git clean -d -f

był niedoceniany ( -d, aby usunąć katalogi). Dzięki!

Anael
źródło
Aby uzyskać pełny, w 100% czysty folder repozytorium bez dodatkowych plików, uruchom git clean -xdf. Spowoduje to usunięcie wszystkich plików, o których git nie wie, i sprawi, że twój folder będzie dokładnie pasował do tego, co znajduje się na liście obiektów git. Pamiętaj, że możesz dodać -n(np. git clean -nxdf), Aby wykonać „co-jeśli”, a powie ci, co zostanie usunięte bez robienia czegokolwiek. ( git clean )
qJake
5

Jeśli chcesz wrócić do HEADstanu zarówno dla katalogu roboczego, jak i indeksu, powinieneś git reset --hard HEADraczej niż HEAD^. (Może to być literówka, tak jak dla pojedynczego kontra podwójnego myślnika --hard.)

Jeśli chodzi o konkretne pytanie, dlaczego pliki te mają status zmodyfikowany, wygląda na to, że wykonałeś miękki reset zamiast twardego. Spowoduje to, że pliki, które zostały zmienione w HEADzatwierdzeniu, będą wyglądały tak, jakby były przemieszczane, co jest prawdopodobnie tym, co tutaj widzisz.

Emil Sit
źródło
4

Żadna ilość resetowania i czyszczenia nie miała żadnego wpływu na nieśledzone i zmodyfikowane pliki w moim lokalnym repozytorium git (wypróbowałem wszystkie powyższe opcje). Moim jedynym rozwiązaniem tego było rm lokalnego repo i sklonowanie go ze zdalnego.

Na szczęście nie miałem innych gałęzi, na których mi zależało.

xkcd: Git

Jaskółka oknówka
źródło
1

Jedyne rozwiązanie, które działa we wszystkich przypadkach, które widziałem, to usuwanie i ponowne klonowanie. Może jest inny sposób, ale oczywiście ten sposób nie pozostawia szansy na pozostanie tam starego państwa, więc wolę. Bash one-liner, który możesz ustawić jako makro, jeśli często psujesz rzeczy w 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

* zakłada, że ​​Twoje pliki .git nie są uszkodzone

sudo
źródło
4
możesz także ponownie zainstalować system operacyjny, jeśli chcesz mieć pewność!
Sebastian Scholle,
1

Czy zapomniałeś utworzyć gałąź funkcji i przez pomyłkę popełniłeś bezpośrednio master?

Możesz teraz utworzyć gałąź funkcji i przywrócić ustawienia główne bez wpływu na środowisko robocze (lokalny system plików), aby uniknąć uruchamiania kompilacji, testów i problemów z blokadami plików:

git checkout -b feature-branch
git branch -f master origin/master
Grastveit
źródło
1

Tylko 3 polecenia sprawią, że będzie działać

git fetch origin
git reset --hard origin/HEAD
git clean -f
Deep Nirmal
źródło
-3

Jeśli nie masz nic przeciwko zapisaniu lokalnych zmian, ale nadal chcesz zaktualizować repozytorium, aby pasowało do źródła / HEAD, możesz po prostu ukryć lokalne zmiany, a następnie pobrać:

git stash
git pull
Micah Walter
źródło