Skasować tylko jeden plik z wielu plików, które zmieniły się w Git?


3068

Jak mogę ukryć tylko jeden z wielu zmienionych plików w moim oddziale?


109
Nie sądzę, aby zaakceptowana odpowiedź @ bukzor była poprawną odpowiedzią na pytanie, jakie zostało zadane. git stash --keep-indexzachowuje indeks, ale ukrywa wszystko - zarówno w indeksie, jak i poza nim.
Raman,

@Antonio Wydaje mi się, że twoja nagroda powinna być osobnym pytaniem, ponieważ pierwotne pytanie nie ma nic wspólnego z TortoiseGit.
JesusFreke

1
@JesusFreke Tak, biorąc pod uwagę wynik, mogłem oszczędzić 50 powtórzeń :) Po prostu to jest pytanie, na które zostaniesz przekierowany, jeśli spróbujesz wyszukać „częściowe skrytki żółwia”. Tortoisegit nie wydaje się być popularnym tematem tutaj stackoverflow.com/questions/tagged/tortoisegit
Antonio

7
>>>>>>>>> git diff -- *filename* > ~/patchpotem git checkout -- *filename*i później możesz ponownie zastosować łatkę za pomocągit apply ~/patch
neaumusic

36
Większość istniejących odpowiedzi poniżej jest nieaktualna. Od wersji 2.13 (Q2 2017) jest obsługiwany przez git stash push [--] [<pathspec>...].
Ohad Schneider,

Odpowiedzi:


1372

Uwaga : następująca odpowiedź dotyczy git przed git 2.13. W przypadku wersji 2.13 i nowszych sprawdź kolejną odpowiedź poniżej .


Ostrzeżenie

Jak zauważono w komentarzach, umieszcza to wszystko w skrytce, zarówno inscenizowane, jak i niestacjonarne. --Keep-index po prostu pozostawia indeks sam po zakończeniu skrytki. Może to powodować konflikty scalania, gdy później wyskakujesz skrytka.


Spowoduje to ukrycie wszystkiego, czego wcześniej nie dodałeś. Tylko git addrzeczy, które chcesz zachować, a następnie uruchom.

git stash --keep-index

Na przykład, jeśli chcesz podzielić stary zatwierdzenie na więcej niż jeden zestaw zmian, możesz użyć tej procedury:

  1. git rebase -i <last good commit>
  2. Oznacz niektóre zmiany jako edit.
  3. git reset HEAD^
  4. git add <files you want to keep in this change>
  5. git stash --keep-index
  6. Napraw wszystko w razie potrzeby. Nie zapomnij o git addżadnych zmianach.
  7. git commit
  8. git stash pop
  9. W razie potrzeby powtórz od # 5.
  10. git rebase --continue

47
Uważam, że to podejście jest znacznie prostsze: stackoverflow.com/a/5506483/457268
k0pernikus

561
Nie jestem pewien, dlaczego jest to głosowane. Wszyscy muszą mieć inne oczekiwania niż ja. W oryginalnym poście jest pytanie „jak ukryć tylko część niezaangażowanych zmian?” Kiedy używam git stash save -k, tak, indeks (zielony w git stat) jest zachowany, ale cały zestaw zmian (zarówno zielony, jak i czerwony) trafia do schowka. Jest to sprzeczne z żądaniem PO: „ukryj tylko niektóre zmiany”. Chcę ukryć tylko część czerwonego (do wykorzystania w przyszłości).
Pistos

70
Jeśli jesteś bardziej zainteresowany odpowiedzią na pytanie postawione przez @Pistos (tak jak ja), spójrz tutaj: stackoverflow.com/questions/5506339/...
Raman

27
@Raman: Doskonale! git stash -pjest dokładnie tym, czego szukałem. Zastanawiam się, czy ten przełącznik został dodany dopiero niedawno.
Pistos

14
OSTRZEŻENIE: git stash --keep-indexjest zepsuty. Jeśli wprowadzisz więcej zmian, spróbuj git stash poppóźniej uzyskać konflikty scalania, ponieważ skrytka zawiera zmienione pliki, które trzymałeś, a nie tylko te, których nie zachowałeś. Na przykład: zmieniam pliki A i B, a następnie przechowuję B, ponieważ chcę przetestować zmiany w A; Znajduję problem z A, który następnie naprawiam; Popełniam A; Teraz nie mogę odblokować, ponieważ stara wersja A znajduje się w schowku bez wyraźnego powodu powodującego konflikt scalania. W praktyce A i B mogą być wieloma plikami, być może nawet obrazami binarnymi lub czymś takim, więc w zasadzie muszę się poddać i stracić B.
rjmunro

3015

Możesz także użyć git stash save -p "my commit message". W ten sposób możesz wybrać, które przystawki mają być dodane do skrytki, a także całe pliki.

Zostaniesz poproszony o kilka działań dla każdego przystojniaka:

   y - stash this hunk
   n - do not stash this hunk
   q - quit; do not stash this hunk or any of the remaining ones
   a - stash this hunk and all later hunks in the file
   d - do not stash this hunk or any of the later hunks in the file
   g - select a hunk to go to
   / - search for a hunk matching the given regex
   j - leave this hunk undecided, see next undecided hunk
   J - leave this hunk undecided, see next hunk
   k - leave this hunk undecided, see previous undecided hunk
   K - leave this hunk undecided, see previous hunk
   s - split the current hunk into smaller hunks
   e - manually edit the current hunk
   ? - print help

5
Nie było. Został pożyczony od Darcs, około 7 lat po fakcie.
nomen

6
Jestem uzależnionym od TortoiseGit. Jednak TortoiseGit nie obsługuje stash -p. Przyznaję tę odpowiedź, ponieważ pozostaje ona najbardziej interaktywna / przyjazna dla użytkownika.
Antonio

27
możesz dodać git stash save -p my stash message:; ponieważ kolejność argumenstów nie jest zbyt intuicyjna ...
Chris Maes,

15
Pomiędzy tym a git log -p, myślę, że -pflaga musi oznaczać „rób fajne rzeczy, które chcę, ale nie umiem wyrazić”.
Kyle Strand

2
dlaczego, u licha, ta świetna odpowiedź jest na 12. pozycji? po tych wszystkich odpowiedziach 0, +1, +2 ??????
DenisFLASH

547

Ponieważ git zasadniczo polega na zarządzaniu całą zawartością i indeksem repozytorium (a nie jednym lub kilkoma plikami), git stashzajmuje się, co nie dziwi,z całym katalogiem roboczym.

W rzeczywistości od wersji Git 2.13 (II kwartał 2017 r.) Można przechowywać poszczególne pliki za pomocą git stash push:

git stash push [--] [<pathspec>...]

Gdy pathspecpodano „ git stash push”, nowa skrytka rejestruje zmodyfikowane stany tylko dla plików, które pasują do specyfikacji ścieżki. Zobacz „Ukrywanie zmian w określonych plikach ”, aby uzyskać więcej.

Uproszczony przykład:

 git stash push path/to/file

Przypadek testowy tej funkcji pokazuje kilka dodatkowych opcji:

test_expect_success 'stash with multiple pathspec arguments' '
    >foo &&
    >bar &&
    >extra &&
    git add foo bar extra &&

    git stash push -- foo bar &&   

    test_path_is_missing bar &&
    test_path_is_missing foo &&
    test_path_is_file extra &&

    git stash pop &&
    test_path_is_file foo &&
    test_path_is_file bar &&
    test_path_is_file extra

Oryginalna odpowiedź (poniżej, czerwiec 2010 r.) Dotyczyła ręcznego wybierania tego, co chcesz ukryć.

Komentarze Casebash :

To ( stash --patchoryginalne rozwiązanie) jest fajne, ale często modyfikowałem wiele plików, więc używanie łatki jest denerwujące

bukzor „s odpowiedź (upvoted, listopad 2011) sugeruje bardziej praktyczne rozwiązanie, oparte na
git add+git stash --keep-index .
Idź i poproś jego odpowiedź, która powinna być oficjalna (zamiast mojej).

O tej opcji chhh wskazuje w komentarzach alternatywny przepływ pracy:

powinieneś „ git reset --soft” po takim skrytce, aby przywrócić czystą inscenizację:
Aby wrócić do pierwotnego stanu - który jest czystym obszarem inscenizacji i tylko z kilkoma wybranymi nieustawionymi modyfikacjami, można delikatnie zresetować indeks, aby uzyskać (bez popełnienie czegoś takiego jak ty - bukzor - zrobiłeś).


(Oryginalna odpowiedź z czerwca 2010: skrytka ręczna)

Jednak git stash save --patchmoże pozwolić na osiągnięcie częściowego ukrywania, którego szukasz:

Za pomocą --patchmożna interakcyjnie wybierać przystawki między różnicą między HEAD a działającym drzewem, które ma być ukryte.
Wpis skrytki jest skonstruowany w taki sposób, że jego stan indeksu jest taki sam jak stan indeksu repozytorium, a jego drzewo robocze zawiera tylko zmiany wybrane interaktywnie. Wybrane zmiany są następnie przywracane z twojego środowiska roboczego.

Spowoduje to jednak zapisanie pełnego indeksu (który może nie być tym, czego chcesz, ponieważ może on zawierać inne pliki już zindeksowane) oraz częściowego drzewa roboczego (które może wyglądać jak ten, który chcesz ukryć).

git stash --patch --no-keep-index

może być lepsze dopasowanie.


Jeśli --patchnie działa, proces ręczny może:

W przypadku jednego lub kilku plików rozwiązaniem pośrednim byłoby:

  • skopiuj je poza repozytorium Git
    (w rzeczywistości eleotlecram proponuje ciekawą alternatywę )
  • git stash
  • skopiuj je z powrotem
  • git stash # tym razem ukryte są tylko te pliki, które chcesz
  • git stash pop stash@{1} # zastosuj ponownie wszystkie modyfikacje plików
  • git checkout -- afile # zresetuj plik do zawartości HEAD, przed wszelkimi lokalnymi modyfikacjami

Pod koniec tego dość uciążliwego procesu będziesz mieć tylko jeden lub kilka plików ukrytych.


3
To miłe, ale często modyfikowałem wiele plików, więc używanie łatki jest denerwujące
Casebash

6
@VonC: Dobrze jest mieć tylko jedną odpowiedź na odpowiedź. Także kopiowanie i wklejanie odpowiedzi innych na własne to złe maniery.
bukzor 12.12.11

3
@bukzor: Przykro mi, jeśli moja zredagowana odpowiedź wydawała się niewłaściwa. Moim jedynym zamiarem było zwiększenie widoczności twojej odpowiedzi. Zredagowałem ponownie swój post, aby wyjaśnić ten zamiar.
VonC,

1
@Kal: true, stackoverflow.com/a/13941132/6309 sugeruje git reset(mieszany)
VonC

3
git is fundamentally about managing a all repository content and index and not one or several files- to implementacja przesłaniająca rozwiązywany problem; to wyjaśnienie, ale nie uzasadnienie. Każdy system kontroli źródła ma na celu „zarządzanie wieloma plikami”. Zobacz, jakie komentarze są najczęściej oceniane.
Victor Sergienko,

90

Kiedy git stash -p(lub git add -pz stash --keep-index) byłoby zbyt uciążliwe, znalazłem to łatwiejsze w użyciu diff, checkoutoraz apply:

Aby „ukryć” tylko określony plik / katalog:

git diff path/to/dir > stashed.diff
git checkout path/to/dir

Potem

git apply stashed.diff

1
Interesująca alternatywa dla git add -pwspomnianej powyżej w mojej odpowiedzi. +1.
VCC

11
Zauważ, że jeśli masz pliki binarne (takie jak PNG), nie będą one wyprowadzane do pliku diff. To nie jest w 100% rozwiązanie.
void.pointer

1
@RobertDailey: To interesujący punkt dla mnie, ponieważ git diff > file.diffi git applysą to moje zwykłe narzędzia do częściowego ukrywania. Być może będę musiał rozważyć zmianę git stash -pna większe zestawy zmian.
thekingoftruth

1
@ thehekingoftruth Oto alias, którego używam do tworzenia plików łatek i tak się dzieje binarnych wsparcia: patch = log --pretty=email --patch-with-stat --reverse --full-index --binary. Pamiętaj jednak, że wymaga to wprowadzenia zmian do zatwierdzenia poprawki.
void.pointer

2
Nie działało to dla mnie dobrze, jeśli plik do ukrycia był podobny ../../foo/bar.txt. Łatka generuje OK, ale muszę przejść do katalogu głównego repozytorium, aby zastosować łatkę. Więc jeśli masz z tym problem - po prostu upewnij się, że robisz to z katalogu głównego repozytorium.
Michael Anderson,

86

Użyj git stash push, jak to:

git stash push [--] [<pathspec>...]

Na przykład:

git stash push -- my/file.sh

Jest to dostępne od Gita 2.13, wydanego wiosną 2017 roku.


1
Ale wspominam git stash pushjuż w mojej odpowiedzi powyżej w marcu, 5 miesięcy temu. I wyszczególniłem tutaj nowe polecenie Git 2.13: stackoverflow.com/a/42963606/6309 .
VonC

Cieszę się, że Git rozwija się tak szybko, przez długi czas nie było to możliwe, a następnie wydano 2.13 i nagle dostępne jest proste rozwiązanie!
sandstrom

1
@VonC masz rację, wspominasz również poprawną odpowiedź, jednak między dwiema odpowiedziami ta jest łatwiejsza do odczytania (bez mylącego tekstu i jest też przykład). Może zamiast tego powinni byli zredagować twoją odpowiedź
Utopik,

@Utopik Miałeś mnie w „masz rację” ... ale tak, zredagowałem swoją odpowiedź, aby podać przykład.
VonC

Czy następnie używa się go git stash applydo odzyskania ukrytych zmian?
Czad

49

Załóżmy, że masz 3 pliki

a.rb
b.rb
c.rb

i chcesz ukryć tylko b.rb i c.rb, ale nie a.rb

możesz zrobić coś takiego

# commit the files temporarily you don't want to stash
git add a.rb
git commit -m "temp" 

# then stash the other files
git stash save "stash message"

# then undo the previous temp commit
git reset --soft HEAD^
git reset

I gotowe! HTH.


29

Inny sposób to zrobić:

# Save everything
git stash 

# Re-apply everything, but keep the stash
git stash apply

git checkout <"files you don't want in your stash">

# Save only the things you wanted saved
git stash

# Re-apply the original state and drop it from your stash
git stash apply stash@{1}
git stash drop stash@{1}

git checkout <"files you put in your stash">

Wymyśliłem to po tym, jak (ponownie) trafiłem na tę stronę i nie podobały mi się dwie pierwsze odpowiedzi (pierwsza odpowiedź po prostu nie odpowiada na pytanie i nie bardzo lubiłem pracę w -ptrybie interaktywnym).

Pomysł jest taki sam, jak sugerowany przez @VonC przy użyciu plików poza repozytorium, zapisujesz zmiany, które chcesz gdzieś, usuwasz zmiany, których nie chcesz, w skrytce, a następnie ponownie stosujesz zmiany, które usunąłeś z drogi. Jednak użyłem skrytki git jako „gdzieś” (w rezultacie na końcu jest jeden dodatkowy krok: usunięcie blokad, które umieściłeś w skrytce, ponieważ również je usunąłeś).


1
Najbardziej podoba mi się to podejście. Zapewnia łatwy przepływ pracy w żółwie przy użyciu tylko poleceń ukrywania i przywracania.
Mark Ch

Odwoływanie się do odpowiedzi dotyczących SO przy użyciu pozycji nie jest wskazane. Pozycje zmieniają się wraz ze zmianami ocen.
Bryan Ash

2
@BryanAsh Cóż, tutaj nie ma to znaczenia. Podaję anegdotę, a nie nawiązuję do innych odpowiedzi. Wiadomość jest taka, że ​​nie podobały mi się odpowiedzi, które lubiła społeczność, a nie to, co one faktycznie zawierają. Poza tym różnica 900 głosów między drugą a trzecią odpowiedzią sprawia, że ​​jest mało prawdopodobne, aby zmieniła się ona w najbliższej przyszłości, a jeśli powinna się zmienić, zawsze mogę ją edytować, aby powiedzieć „top of the respond at the time”. Naprawdę nie rozumiem, w jaki sposób jest to jakiś problem w tej sytuacji.
Jasper

23

Aktualizacja (14.02.2015) - Napisałem nieco skrypt, aby lepiej obsługiwać przypadki konfliktów, które powinny być teraz przedstawiane jako konflikty nie połączone, a nie pliki .rej.


Często intuicyjnie jest robić odwrotność podejścia @ bukzora. To znaczy, aby wprowadzić pewne zmiany, a następnie ukryć tylko te zmiany etapowe.

Niestety, git nie oferuje skrytki git - tylko indeksowej lub podobnej, więc wymyśliłem skrypt, aby to zrobić.

#!/bin/sh

# first, go to the root of the git repo
cd `git rev-parse --show-toplevel`

# create a commit with only the stuff in staging
INDEXTREE=`git write-tree`
INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD`

# create a child commit with the changes in the working tree
git add -A
WORKINGTREE=`git write-tree`
WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard

# Cherry-pick the index changes back to the index, and stash.
# This cherry-pick is guaranteed to succeed
git cherry-pick -n $INDEXCOMMIT
git stash

# Now cherry-pick the working tree changes. This cherry-pick may fail
# due to conflicts
git cherry-pick -n $WORKINGCOMMIT

CONFLICTS=`git ls-files -u`
if test -z "$CONFLICTS"; then
    # If there are no conflicts, it's safe to reset, so that
    # any previously unstaged changes remain unstaged
    #
    # However, if there are conflicts, then we don't want to reset the files
    # and lose the merge/conflict info.
    git reset -q
fi

Możesz zapisać powyższy skrypt git-stash-indexgdzieś na swojej ścieżce, a następnie wywołać go jako git stash-index

# <hack hack hack>
git add <files that you want to stash>
git stash-index

Teraz skrytka zawiera nowy wpis, który zawiera tylko zmiany, które zainscenizowałeś, a twoje drzewo robocze nadal zawiera wszelkie zmiany niestacjonarne.

W niektórych przypadkach zmiany działającego drzewa mogą zależeć od zmian indeksu, więc gdy ukryjesz zmiany indeksu, zmiany w drzewie roboczym będą powodowały konflikt. W takim przypadku otrzymasz zwykłe nierozłączone konflikty, które możesz rozwiązać za pomocą git merge / git scaletool / etc.


Polecaj pushdzamiast cdi popdna końcu skryptu, więc jeśli skrypt się powiedzie, użytkownik znajdzie się w tym samym katalogu, co przed uruchomieniem.
Nate

1
@Nate: o ile wiem, powinien zmienić katalog dla użytkownika, tylko jeśli pozyskał skrypt. Jeśli skrypt zostanie uruchomiony normalnie (~ / bin / git-stash-index) lub za pomocą git (git stash-index), zostanie on uruchomiony w osobnej sesji terminala, a wszelkie zmiany katalogu roboczego w tej sesji nie będą miały wpływu na katalog roboczy w sesji terminalu użytkownika. Czy zdajesz sobie sprawę z typowego przypadku użycia, gdy nie jest to prawda? (poza pozyskiwaniem skryptu, którego nie
uważałbym

20

Jeśli nie chcesz określać wiadomości z ukrytymi zmianami, podaj nazwę pliku po podwójnym myślniku.

$ git stash -- filename.ext

Jeśli jest to nieśledzony / nowy plik, najpierw musisz go wyeksponować.

Ta metoda działa w wersjach git 2.13+


Ta odpowiedź jest pełna, to jest zwięzłe. Jeśli to komuś pomoże, zostawię to. Nikt na tej stronie nie wspomina o tej składni i wyniku - zamiast tego wspomina o `git stash push`.
sealocal

Oto odpowiedź, której szukałem. Dzięki! +1
nicodp

19

Ponieważ tworzenie gałęzi w Git jest banalne, możesz po prostu utworzyć gałąź tymczasową i sprawdzić w niej poszczególne pliki.


2
Nie można utworzyć gałęzi bez edycji etapowej. Możesz łatwo przenieść wszystkie zmiany do nowej gałęzi (ukryty / ukryty pop), ale potem wracasz do pierwszej: jak przetestujesz swoją gałąź tylko z niektórymi edycjami, nie tracąc pozostałych?
bukzor

7
Nie możesz zmieniać oddziałów, jeśli masz zmiany lokalne. Możesz jednak utworzyć nową gałąź i selektywnie dodawać / zatwierdzać pliki, a następnie utworzyć inną gałąź i zrobić to samo rekurencyjnie ... następnie pobrać oryginalną gałąź i selektywnie scalić się ponownie. Właśnie to zrobiłem. W rzeczywistości wydaje się to naturalnym sposobem na robienie rzeczy, ponieważ zasadniczo tworzysz gałęzie funkcji.
iain

3
@iain możesz zmieniać oddziały, jeśli masz zmiany lokalne, o ile nie wymagają one scalenia. Zobacz przykład Gist . Dotyczy to przynajmniej wersji Git v2.7.0.
Colin D Bennett,

18

Możesz po prostu to zrobić:

git stash push "filename"

lub z opcjonalnym komunikatem

git stash push -m "Some message" "filename"

1
To nie dodaje nic nowego. Git stash push jest już wspomniany w wielu odpowiedziach
JesusFreke

12

Zapisz następujący kod w pliku, na przykład o nazwie stash. Wykorzystanie jest stash <filename_regex>. Argument jest wyrażeniem regularnym dla pełnej ścieżki pliku. Na przykład, aby ukryć plik a / b / c.txt stash a/b/c.txtlub stash .*/c.txtitp.

$ chmod +x stash
$ stash .*.xml
$ stash xyz.xml

Kod do skopiowania do pliku:

#! /usr/bin/expect --
log_user 0
set filename_regexp [lindex $argv 0]

spawn git stash -p

for {} 1 {} {
  expect {
    -re "diff --git a/($filename_regexp) " {
      set filename $expect_out(1,string)
    }
    "diff --git a/" {
      set filename ""
    }
    "Stash this hunk " {
      if {$filename == ""} {
        send "n\n"
      } else {
        send "a\n"
        send_user "$filename\n"
      }
    }
    "Stash deletion " {
      send "n\n"
    }
    eof {
      exit
    }
  }
}

2
Świetna metoda. Wybrałbym to jako odpowiedź. Wskazówka dla przyszłych czytelników: musisz dopasować pełną ścieżkę. np. stash subdir / foo.c
er0

12

Na wypadek, gdybyś naprawdę miał na myśli odrzucić zmiany za każdym razem, gdy używasz git stash(i tak naprawdę nie używasz git stash do tymczasowego przechowywania), w takim przypadku możesz użyć

git checkout -- <file>

[ UWAGA ]

To git stashtylko szybsza i prosta alternatywa dla rozgałęziania i robienia rzeczy.


8

Problem z „pośrednim” rozwiązaniem VonC polegającym na kopiowaniu plików poza repozytorium Git polega na tym, że tracisz informacje o ścieżce, co sprawia, że ​​kopiowanie wiązki plików jest nieco kłopotliwe.

Łatwiej jest użyć tar (prawdopodobnie podobne narzędzia); zamiast kopiować:

  • tar cvf /tmp/stash.tar path / to / some / file path / to / some / other / file (... itd.)
  • git checkout path / to / some / file path / to / some / other / file
  • git skrytka
  • tar xvf /tmp/stash.tar
  • itp. (patrz sugestia „pośrednia” VonC)

checkout -fnie jest potrzebne, wystarczy checkout(bez -f), zaktualizowałem odpowiedź.
eleotlecram

8

Czasami dokonałem niepowiązanej zmiany w moim oddziale, zanim go dokonałem, i chcę przenieść go do innej gałęzi i zatwierdzić osobno (np. Master). Robię to:

git stash
git checkout master
git stash pop
git add <files that you want to commit>
git commit -m 'Minor feature'
git stash
git checkout topic1
git stash pop
...<resume work>...

Uwaga pierwsza stashi stash popmogą być wyeliminowane, można nosić wszystkie swoje przejście do masteroddziału po kasę, ale tylko wtedy, gdy nie ma żadnych konfliktów. Również jeśli tworzysz nową gałąź dla częściowych zmian, będziesz potrzebował skrytki.

Możesz to uprościć, zakładając brak konfliktów i brak nowej gałęzi:

git checkout master
git add <files that you want to commit>
git commit -m 'Minor feature'
git checkout topic1
...<resume work>...

Skrytka nawet nie potrzebna ...


8

Można to zrobić w 3 krokach za pomocą SourceTree.

  1. Tymczasowo popełnij wszystko, czego nie chcesz przechowywać.
  2. Dodaj wszystko inne, a następnie schowaj.
  3. Pop tymczasowe zatwierdzenie, uruchamiając git reset, celując w zatwierdzenie przed tymczasowym.

Można to wszystko zrobić w ciągu kilku sekund w SourceTree, gdzie możesz po prostu kliknąć pliki (lub nawet pojedyncze linie), które chcesz dodać. Po dodaniu wystarczy zatwierdzić je do tymczasowego zatwierdzenia. Następnie kliknij pole wyboru, aby dodać wszystkie zmiany, a następnie kliknij ukryj, aby ukryć wszystko. Po usunięciu ukrytych zmian, rzuć okiem na listę zatwierdzeń i zanotuj skrót dla zatwierdzenia przed tymczasowym zatwierdzeniem, a następnie uruchom polecenie „git reset hash_b4_temp_commit”, co w zasadzie przypomina „wyskakiwanie” zatwierdzenia przez zresetowanie gałęzi do popełnić tuż przed tym. Teraz masz tylko rzeczy, których nie chciałeś schować.


8

Chciałbym użyć git stash save --patch. Uważam, że interaktywność nie jest denerwująca, ponieważ istnieją opcje pozwalające zastosować żądaną operację do całych plików.


3
Dziwię się, że tak mało jest poparcia dla tej odpowiedzi, to najlepsze rozwiązanie bez potrzeby eseju.
robstarbuck

Zdecydowanie dobra odpowiedź, git stash -ppozwala szybko schować cały plik i wyjść z niego później.
Richard Dally,

7

Każda odpowiedź tutaj jest tak skomplikowana ...

Co z tym „ukryć”:

git diff /dir/to/file/file_to_stash > /tmp/stash.patch
git checkout -- /dir/to/file/file_to_stash

Aby cofnąć zmianę pliku:

git apply /tmp/stash.patch

Dokładnie takie samo zachowanie, jak ukrycie jednego pliku i ponowne włożenie go z powrotem.


Próbowałem, ale nic się nie stało. Gdy nie git applymam błędu, ale zmiany nie są przywracane
ClementWalter 10.04.17.04

Plik poprawki wygenerowany w / tmp został prawdopodobnie usunięty. Możliwe, że uruchomiłeś się ponownie między różnicą a aplikacją. Wypróbuj inną, bardziej stałą lokalizację. To działa. Sprawdź także zawartość pliku poprawki.
Christophe Fondacci

4

Przejrzałem odpowiedzi i komentarze na ten temat i kilka podobnych wątków. Należy pamiętać, że żadne z poniższych poleceń nie jest poprawne, aby móc przechowywać określone pliki śledzone / nieśledzone :

  • git stash -p (--patch): wybierz porcje ręcznie, z wyłączeniem nieśledzonych plików
  • git stash -k (--keep-index): ukryj wszystkie śledzone / nieśledzone pliki i przechowuj je w katalogu roboczym
  • git stash -u (--include-untracked): ukryj wszystkie śledzone / nieśledzone pliki
  • git stash -p (--patch) -u (--include-untracked): niepoprawna komenda

Obecnie najbardziej rozsądnym sposobem na ukrycie określonych plików śledzonych / nieśledzonych jest:

  • Tymczasowo zatwierdź pliki, których nie chcesz przechowywać
  • Dodaj i schowaj
  • Pop tymczasowe zatwierdzenie

Napisałem prosty skrypt dla tej procedury w odpowiedzi na inne pytanie , a tutaj są kroki do wykonania procedury w SourceTree .


4

Rozwiązanie

Zmiany lokalne:

  • plik_A (zmodyfikowany) nie jest przemieszczany
  • plik_B (zmodyfikowany) nie jest przemieszczany
  • plik_C (zmodyfikowany) nie jest przemieszczany

Aby utworzyć skrytkę „my_stash” ze zmianami tylko w file_C :

1. git add file_C
2. git stash save --keep-index temp_stash
3. git stash save my_stash
4. git stash pop stash@#{1}

Gotowy.


Wyjaśnienie

  1. dodaj plik_C do obszaru przejściowego
  2. utwórz tymczasową skrytkę o nazwie „temp_stash” i zachowaj zmiany w pliku file_C
  3. utwórz żądaną skrytkę („my_stash”), wprowadzając tylko zmiany w pliku file_C
  4. zastosuj zmiany w „temp_stash” (plik_A i plik_B) w swoim lokalnym kodzie i usuń skrytkę

Możesz użyć statusu git między krokami, aby zobaczyć, co się dzieje.


3

Taka sytuacja występuje podczas próby przełączenia między dwiema gałęziami.

Spróbuj dodać pliki, używając „ git add filepath”.

Później wykonaj tę linię

git stash --keep-index


3

Do przechowywania jednego pliku użyj git stash --patch [file].

To będzie szybka: Stash this hunk [y,n,q,a,d,j,J,g,/,e,?]? ?. Po prostu wpisz a(ukryj ten kawałek i wszystkie późniejsze fragmenty w pliku) i nic ci nie będzie.


Zaginiony pushjak wgit stash push --patch [file]
Filipe Esperandio

@FilipeEsperandio pushdziała tylko w nowszych wersjach Git, kiedyś save. W obu przypadkach pushlub savesą implikowane przez wywołanie stash: „Wywołanie git stash bez żadnych argumentów jest równoważne z git stash push”, docs
Patrick

2

Podobna sytuacja. Zatwierdziłem i zdałem sobie sprawę, że to nie jest w porządku.

git commit -a -m "message"
git log -p

Na podstawie odpowiedzi pomogło mi to.

# revert to previous state, keeping the files changed
git reset HEAD~
#make sure it's ok
git diff
git status
#revert the file we don't want to be within the commit
git checkout specs/nagios/nagios.spec
#make sure it's ok
git status
git diff
#now go ahead with commit
git commit -a -m "same|new message"
#eventually push tu remote
git push

2

W tej sytuacji ja git add -p(interaktywnie), git commit -m blaha następnie chowam, co pozostało, jeśli to konieczne.


2

Nie wiem, jak to zrobić w wierszu poleceń, używając tylko SourceTree. Powiedzmy, że zmieniłeś plik A i masz dwa porcje zmian w pliku B. Jeśli chcesz ukryć tylko drugi przystojniak w pliku B i pozostawić wszystko inne bez zmian, wykonaj następujące czynności:

  1. Pokaż wszystko
  2. Wprowadź zmiany w kopii roboczej, które cofną wszystkie zmiany w pliku A. (np. Uruchom zewnętrzne narzędzie do porównywania i dopasuj pliki).
  3. Spraw, aby plik B wyglądał tak, jakby zastosowano do niego tylko drugą zmianę. (np. uruchom zewnętrzne narzędzie do porównywania i cofnij pierwszą zmianę).
  4. Utwórz skrytkę za pomocą opcji „Zachowaj zmiany etapowe”.
  5. Pokaż wszystko
  6. Gotowy!

2
git add .                           //stage all the files
git reset <pathToFileWillBeStashed> //unstage file which will be stashed
git stash                           //stash the file(s)
git reset .                         // unstage all staged files
git stash pop                       // unstash file(s)

1
Nie powinieneś tego robić. Odpowiedź powinna stanowić rozwiązanie kwestii. Możesz po prostu zadać własne pytanie.
L_J

to rozwiązanie jest jedną z najłatwiejszych odpowiedzi na to pytanie. przeczytaj pytanie, porównaj wszystkie odpowiedzi i moje, a jeśli masz jakiekolwiek wątpliwości, że ta odpowiedź nie jest odpowiednim rozwiązaniem ani niewystarczającą informacją o pytaniu, możemy porozmawiać ponownie.
celikz

To nie zadziała, ponieważ trzecie polecenie „git stash” nie będzie honorować przemieszczanych plików. Zarówno pliki etapowe, jak i niestacjonarne trafią do magazynu. Pytania w szczególności dotyczą sposobu
przechowywania

0

Jednym skomplikowanym sposobem byłoby najpierw zatwierdzenie wszystkiego:

git add -u
git commit // creates commit with sha-1 A

Zresetuj z powrotem do pierwotnego zatwierdzenia, ale pobieraj plik_jedna z nowego zatwierdzenia:

git reset --hard HEAD^
git checkout A path/to/the_one_file

Teraz możesz ukryć jeden_plik_pliku:

git stash

Oczyszczanie poprzez zapisanie zatwierdzonej zawartości w systemie plików podczas resetowania do pierwotnego zatwierdzenia:

git reset --hard A
git reset --soft HEAD^

Tak, trochę niezręcznie ...


0

Nie znalazłem odpowiedzi na to, czego potrzebowałem, a to jest tak proste, jak:

git add -A
git reset HEAD fileThatYouWantToStash
git commit -m "committing all but one file"
git stash

Skrywa to dokładnie jeden plik.


0

Szybka odpowiedź


Aby przywrócić określony zmieniony plik w git, możesz wykonać następujący wiersz:

git checkout <branch-name> -- <file-path>

Oto rzeczywisty przykład:

git checkout master -- battery_monitoring/msg_passing.py


0

Jeśli chcesz ukryć niektóre zmienione pliki, po prostu

Dodaj pliki, których nie chcesz ukrywać, na etapie , a następnie uruchomgit stash save --keep-index

Przechowa wszystkie niestabilne zmienione pliki

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.