git-Kasse . entfernt keine Dateien, die nach dem Commit hinzugefügt wurden

Lesezeit: 7 Minuten

Benutzeravatar von mulllhausen
Müllhausen

Mit einem öffentlichen Repo möchte ich meinen Master-Zweig auf einen bestimmten Commit aus der Vergangenheit zurückführen. Ich habe die Optionen überprüft und das Beste für mich scheint ein einfaches Auschecken zum gewünschten Commit zu sein, dann ein Commit zum Master-Zweig. Wenn ich jedoch den Checkout durchführe, werden einige Dateien nicht entfernt, die nach dem angegebenen Commit-Hash zum Master hinzugefügt wurden.

Also zum Beispiel, wenn ich zurückkommen möchte, um mich zu verpflichten aaa1:

$ cd working-copy-top-dir
$ git checkout master
$ git checkout -- .
$ git clean -fd
$ git checkout aaa1 .
$ git clean -fd

Aber an dieser Stelle wurden einige Dateien nachher hinzugefügt aaa1 befinden sich noch in der Arbeitskopie. Was ist der checkout Befehl, um die Arbeitskopie zu erhalten Daten zurück, wie es war aaa1?

$ git --version
git version 2.7.2.windows.1

  • Es kann an der Art der Kasse liegen, die ich auf stackoverflow.com/a/14460890/339874 durchgeführt habe

    – Müllhausen

    13. Mai 2016 um 4:22 Uhr

  • Ich denke, Sie müssen es versuchen git zurücksetzen.

    – BETEN

    13. Mai 2016 um 5:16 Uhr

  • Siehe auch stackoverflow.com/questions/4114095/…

    – Torek

    13. Mai 2016 um 7:33 Uhr

TL;DR: zuerst alles entfernen

Als Sie verwendet haben git checkout aaa1 .du hast Git gesagt, dass es übersetzen soll aaa1 zu einem Commit, suchen Sie dieses Commit (genauer gesagt, seinen Baum) und kopieren Sie jede Datei in diesem Commit in Ihren Index / Staging-Bereich und Arbeitsbaum.

Sagen wir, nur um der Argumentation willen, dass Sie damit beginnen master enthält zwei Dateien, README und hello:

$ git checkout master
[output snipped]
$ ls
README   hello
$ cat README
Yay, you read me!
$ cat hello
world
$ 

Sagen wir weiter, dass Commit aaa1 existiert und enthält zwei Dateien, README und addendum. Es ist README sagt Thank you for reading. Lassen Sie uns diese Kasse machen:

$ git checkout aaa1 -- .
[output snipped]
$ ls
README    addendum  hello

(Ich habe die hinzugefügt --: Es ist hier eigentlich nicht erforderlich, aber es ist eine gute Übung.) Der Inhalt von README sind die aktualisierten README. Die Datei addendum wurde ebenfalls extrahiert. Die Datei hello ist nicht entfernt und bleibt gegenüber der Version in unverändert master. Die aktualisiert README und hello werden inszeniert:

$ git status --short
M  README
A  addendum

sondern hello wird nicht entfernt:

$ git ls-files --stage
100644 ac6f2cf1acbe1b6f11c7be2288fbae72b982823c 0   README
100644 7ddf1d71e0209a8512fe4862b4689d6ff542bf99 0   addendum
100644 cc628ccd10742baea8241c5924df992b5c019f71 0   hello

Verwenden git cleansogar mit -x, wird keine Wirkung haben: nichts muss gereinigt werden; Es gibt keine nicht bereitgestellten Dateien (hello ist inszeniert, es ist einfach nicht geändert).


Sie wollten ausdrücklich, dass der Arbeitsbaum mit dem Commit übereinstimmt aaa1, Byte für Byte. Dazu müssen Sie Dateien finden, die jetzt im Index sind, aber nicht darin waren aaa1und entfernen Sie sie.

Es gibt jedoch einen einfacheren Weg: einfach entfernen alles. Verwenden Sie dann Ihre git checkout aaa1 -- . alles herausholen aaa1. Dies füllt den Index und den Arbeitsbaum aus aaa1: Alle Dateien, die so wiederhergestellt werden müssen, wie sie vor dem Entfernen waren, werden wiederhergestellt (so, wie sie in aaa1 welches ist das gleiche so wie sie drin sind HEAD). Alle Dateien, die geändert werden müssen, damit sie mit der Art und Weise übereinstimmen, in der sie sich befanden aaa1werden wiederhergestellt (so wie sie waren aaa1 welches ist anders).

$ git rm -rf .
rm 'README'
rm 'addendum'
rm 'hello'
$ git checkout aaa1 -- .
$ git ls-files --stage
100644 ac6f2cf1acbe1b6f11c7be2288fbae72b982823c 0   README
100644 7ddf1d71e0209a8512fe4862b4689d6ff542bf99 0   addendum
$ git status --short
M  README
A  addendum
D  hello

Sie können jetzt ein Commit durchführen und haben ein neues Commit master das, egal was vorher da war, genau den gleichen Baum hat wie aaa1.

(Ob das ein gute Idee ist eine ganz andere Sache, aber es wird Ihnen den gewünschten Zustand verschaffen.)

Benutzeravatar von pRaNaY
PraNaY

Möchten Sie Ihr Repo auf diesen Zustand zurücksetzen? Oder möchten Sie einfach, dass Ihr lokales Repo so aussieht?

Sehen https://git-scm.com/docs/git-reset für Git-Reset.

FALL 1:
wenn Sie tun

git reset --hard [commit hash]

Dadurch werden Ihr lokaler Code und Ihr lokaler Verlauf genauso wie bei diesem Commit. Aber wenn Sie dies jemand anderem mitteilen wollten, der die neue Historie hat, würde dies scheitern.

FALL 2: wenn Sie tun

git reset --soft [commit hash]

Dadurch werden Ihre lokalen Dateien so geändert, wie sie damals waren, aber Ihr Verlauf usw. bleibt unverändert.

Ich habe hier eine Antwort gefunden. Hier können Sie auch die zugehörige Antwort sehen.

  • Es ist ein öffentliches Repo, also git reset --soft ist was ich brauche 🙂

    – Müllhausen

    13. Mai 2016 um 5:34 Uhr

  • hmm git reset --soft aaa1 löscht die danach hinzugefügten Dateien nicht aaa1 entweder. Wenn ich in meine Arbeitskopie schaue, sind sie immer noch da

    – Müllhausen

    13. Mai 2016 um 5:46 Uhr


  • JA, freut mich zu wissen, dass es dir hilft.

    – BETEN

    13. Mai 2016 um 6:29 Uhr


  • Entschuldigung, das ist falsch. git reset --soft <commit-hash> tut nicht Ändern Sie die lokalen Dateien, wie in der Manpage erwähnt: --soft Does not the the index file or the working tree at all, but reset the head to <commit>

    – Flimmer

    31. August 2017 um 11:09 Uhr

Benutzeravatar von mulllhausen
Müllhausen

Git checkout entfernt keine Dateien, die seit einem vorherigen Commit hinzugefügt wurden. Dazu bräuchte ich git revert.

Allerdings finde ich git checkout thehash . viel einfacher zu verwenden, und es ist nicht so schwer zu sehen, welche Dateien seit diesem Hash hinzugefügt wurden:

git diff --name-status HEAD thehash

Ich habe festgestellt, dass dieser Befehl sowohl den Index als auch die Arbeitskopie auf den gewünschten Commit aktualisiert, der durch die Variable angegeben wird treeish in diesem Fall:

# use with care: destroys any uncommitted changes
git read-tree "$treeish" --reset -u

Um die Arbeitskopie zu aktualisieren, ohne den Index zu aktualisieren, könnten Sie vielleicht so etwas tun:

index_bak=$(git write-tree)
git read-tree "$treeish" --reset -u
git read-tree "$index_bak" --reset

git checkout --no-overlay (git 2.22.0, Juni 2019)

Damit läuft diese Option:

git checkout --no-overlay <commit> <directory>

entfernt alle Dateien, die unter hinzugefügt wurden <directory> nach <commit>. Ich wünschte, das wäre das Standardverhalten, aber c’est la vie.

Die Option war hinzugefügt von Thomas Gummerer unter 091e04bc8cbb0c89c8112c4784f02a44decc257e was in git ging v2.22.0.

Prüfen:

#!/usr/bin/env bash
set -eu

rm -rf tmp
mkdir tmp
cd tmp
git init

mkdir a
touch a/a
git add .
git commit -m a

mkdir b
touch b/b
git add .
git commit -m b

git checkout HEAD~ .
echo 'overlay'
ls -l . a b

git checkout --no-overlay HEAD~ .
echo 'no overlay'
ls -l . a b

Ergebnis:

git checkout HEAD~ .
echo 'overlay'
ls -l . a b
echo

git checkout --no-overlay HEAD~ .
echo 'no overlay'
ls -l . a b
echo

Ausgabe:

Initialized empty Git repository in /home/ciro/test/git/tmp/.git/
[master (root-commit) 216d22e] a
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a/a
[master a36e67b] b
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 b/b
overlay
.:
total 2
drwxrwxr-x 2 ciro ciro 3 Jan 17 08:40 a
drwxrwxr-x 2 ciro ciro 3 Jan 17 08:40 b

a:
total 1
-rw-rw-r-- 1 ciro ciro 0 Jan 17 08:40 a

b:
total 1
-rw-rw-r-- 1 ciro ciro 0 Jan 17 08:40 b

no overlay
ls: cannot access 'b': No such file or directory
.:
total 1
drwxrwxr-x 2 ciro ciro 3 Jan 17 08:40 a

a:
total 1
-rw-rw-r-- 1 ciro ciro 0 Jan 17 08:40 a

Das sehen wir also b/b wird nur mit entfernt --no-overlay. Das Verzeichnis b wird dann auch wie üblich in git-Befehlen entfernt, weil es durch den git-Befehl leer geworden wäre.

Getestet auf Ubuntu 22.10, Git 2.37.2.

Benutzeravatar von ElpieKay
ElpieKay

git stash ist möglicherweise der schnellste Weg, um den Arbeitsbaum zu bereinigen. und dann git checkout -b $newbranch $commit-sha1-you-want um einen Zweig zu erstellen, mit dem Sie arbeiten werden. Nachdem all deine Arbeit getan ist, Git Stash-Pop um den funktionierenden Baum wiederherzustellen.

1440160cookie-checkgit-Kasse . entfernt keine Dateien, die nach dem Commit hinzugefügt wurden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy