2013-07-30 9 views
7

Angenommen, ich habe ein Repository mit einer Revisionsnummer A. Und ich möchte es auf Revision B aktualisieren, während die neueste Revision C. (Revision A ist früher als B, und B ist früher als C). Ich bin neu in git so habe ich einige der Forschung und fand this, das inspiriert mich eine Lösung:Git: Update eines Repositorys auf bestimmte Revision

git pull # update from A to the latest revision C 
git reset --hard B 

, das funktioniert. Aber da ich von A nicht direkt git reset --hard B kann, ist das Präzedenzfall-Update zu spät immer noch zu schwer, ich frage mich, ob es vielleicht einen einzeiligen Befehl geben könnte, der meinem Bedarf entspricht. Irgendwelche Hinweise bitte?

Antwort

14

Es gibt kein "Update eines Repositorys auf eine bestimmte Version". Ihr Repository hat alle Versionen, das ist git fetch/git pull.

Wenn Sie eine bestimmte Revision des Repos in Ihrem aktuellen Arbeitsbaum lokal einfügen möchten, gibt es mehrere Möglichkeiten, dies zu tun. In der Nähe von Fragen ist:

Update Ihr lokales Repository:

git fetch origin 

eine Niederlassung schaffen (von was auch immer Zweig Sie sich gerade befinden, werden wir später zurückgesetzt hart, so spielt es keine Rolle):

git branch yourbranchname 
git checkout yourbranchname 

2 die obigen Operationen können in eine (die aktuelle HEAD wird angenommen, als Quelle der Verzweigung) abgekürzt werden:

git checkout -b yourbranchname 

dann den Zeiger dieses Zweiges dem Festschreiben Sie brauchen (B):

git reset --hard sha1-of-B 

git reset --hard wird immer funktionieren, ist es nicht auf dem Zweig der Geschichte abhängt, die einzige Bedingung dafür Arbeit ist, dass Commit B ist in Ihrer lokalen Objektbasis (dh B muss existieren und muss von einem entfernten Repo geholt worden sein, ist es nicht Ihre Arbeit).

Wie @Hasturkun weist darauf hin, können Sie auch direkt von jedem beliebigen Hash mit einem zusätzlichen Argument verzweigen:

git checkout -b yourbranchname SHA-1 
+4

Sie müssen die Verzweigung nicht wirklich zurücksetzen, da Sie sie einfach mit dem Anfangspunkt erstellen können, wo Sie ihn haben wollen, dh.'git branch newbranch SHA1-of-B' oder' git checkout -b newbranch SHA1-of-B' – Hasturkun

+0

@ Sébastien Danke für die Einführung einiger grundlegender Konzepte. –

+0

@Hasturkun Ihre Antwort funktioniert perfekt für mich, danke. –

5

Sie müssen dafür git checkout verwenden. Just do:

git checkout B

und Sie werden diese Revision haben.

+0

Danke, aber ich habe einen Fehler mit 'git checkout':' Referenz ist kein Baum'. –

+0

Ich denke, Hasturkun Kommentar in Sébastien Dawans Antwort wird das Problem für Sie beheben. – jbr

1

Ihr Ansatz völlig falsch ist. Sie ändern etwas, das Sie nicht ändern möchten: Ihre aktuelle Verzweigung (vermutlich master).

Eine einfache, lineare git-Repository ist eine Kette von Commits wie diese

*---A---*---*---B---*---*---C 
    ^     ^
    |      | 
    master    origin/master 
    ^
    | 
    HEAD 

, dass der Zustand des Repository ist, nachdem Sie git fetch genannt hast. Beachten Sie, dass sich der gesamte Verlauf mit allen Zwischenschritten direkt auf Ihrer lokalen Festplatte befindet. Es ist nur, dass Sie nur den Zustand bei der Übergabe A ausgecheckt haben (HEAD Punkte auf master, die auf A zeigt), so dass die Dateien, die Sie sehen, zu diesem Zustand gehören.

Wenn Sie jetzt nur den Status sehen möchten, der als B festgeschrieben wurde, können Sie das Commit mit git checkout B überprüfen. Dies aktualisiert die Dateien, die Sie auf den Zustand der B sehen, und weist HEAD an diesem begehen:

*---A---*---*---B---*---*---C 
    ^  ^  ^
    |   |   | 
    master  HEAD origin/master 

HEAD immer verweist auf die Durchführungs-/Zweig, der git denkt man an sind, und auf die sie Ihr Arbeitsverzeichnis vergleichen wenn Sie git status anrufen.

Die einfache git checkout B ist ausreichend, wenn Sie nur diese Commit betrachten möchten. Wenn Sie tatsächlich Änderungen vornehmen möchten, die Sie übernehmen und beibehalten möchten, sollten Sie einen neuen Zweig einführen, um diese Änderungen aufzuzeichnen. Dies wird durch eine einfache git checkout -b newBranch nach der git checkout B erreicht. Dies gibt Ihnen den Zustand

*---A---*---*---B---*---*---C 
    ^  ^  ^
    |   |   | 
    master newBranch origin/master 
       ^
       | 
       HEAD 

Dies gibt nur einen Namen B anderen als seinen Hash-Wert zu begehen.

*---A---*---*---B---*---*---C 
    ^   |   ^
    |   |   | 
    master   \ origin/master 
        \ 
        *---*---D 
          ^
          | 
         newBranch 
          ^
          | 
          HEAD 

Der Punkt ist, dass, nachdem eine andere Zweig Check-out/commit mit git checkout ..., können Sie immer wieder ohne Probleme durch den Aufruf git checkout newBranch zu begehen D und das: Nach einigen Commits, Ihr Zustand würde wie folgt aussehen permanente Referenz stoppt git von Müll sammeln commit D.


Nun, warum wird git reset --hard schlecht verwendet? Zunächst einmal klemmt es alle Ihre lokalen Änderungen, die Sie noch nicht ohne weitere Ankündigung begangen haben. Zweitens kann es Ihnen Geschichte verlieren, wenn Sie nicht vorsichtig damit sind.

Betrachten Sie zum Beispiel den Fall, dass Sie einige Änderungen vorgenommen haben, nachdem Sie zuletzt in Ihr Upstream-Repository verschoben wurden, und einen Blick auf einige historische Commit B werfen möchten. (. Etwas das Gegenteil der Fall in Ihrer Frage) Die Geschichte sieht wie folgt aus:

*---A---*---*---B---*---*---C 
    ^     ^
     |      | 
origin/master    master 
          ^
           | 
          HEAD 

Mit git reset --hard B, können Sie diesen Zustand erhalten:

*---A---*---*---B-(-*---*---C) 
    ^  ^
     |   | 
origin/master master 
       ^
        | 
       HEAD 

Die Commits in Klammern sind nicht direkt referenziert oder indirekt durch jeden Zweig, und kann Müll jederzeit gesammelt werden. git möglicherweise nicht sehr aggressiv mit Müll sammeln, aber wenn es Müll sammelt sammeln, während Sie in diesem Zustand sind, gibt es keine Möglichkeit für Sie, C zurück zu bekommen, wird es für immer verloren. Sie wollen nicht, dass dies geschieht, also ist es keine gute Idee, sich an die Gewohnheit zu gewöhnen, git reset --hard leicht zu verwenden.

Haben Sie git checkout stattdessen verwendet, der Zweig master noch C gerichtet sein würde, und Sie würden noch in der Lage sein, zurück, um es mit einer einfachen git checkout master zu bekommen.

Verwandte Themen