Wie konvertiere ich ein Bare-Git-Repository in ein normales (In-Place)?

81

Ich habe ein Bare-Git-Repository, muss aber über ssh auf dessen Inhalt zugreifen und ihn durchsuchen (in einem Dateimanager wie User Experience).

Ich nehme an, ich könnte es klonen:

git clone -l <path_to_bare_repo> <new_normal_repo>

Mein Repository ist jedoch ungefähr 20 GB groß und ich habe nicht den Speicherplatz, um es zu duplizieren. Gibt es eine Möglichkeit, das nackte Repository direkt zu konvertieren, um eine Arbeitskopie zu erhalten?

Nyi
quelle
5
Ungetestet, aber wenn Sie den Inhalt des Bare-Repositorys in ein .gitVerzeichnis verschieben und den bareParameter in der Konfiguration auf false setzen, sollte es sich wie ein reguläres Repository verhalten, in dem Sie nur git checkoutIhre Dateien abrufen können.
Noufal Ibrahim
Je nachdem , was Sie mit „Durchsuchen seinen Inhalt“, können Sie wahrscheinlich tun alles , was Sie in einem kahlen Repo verwenden möchten git showundgit cat-file
William Pursell
Danke für den Hinweis, nützlich. Ich brauche allerdings einen Dateimanager wie Erfahrung (die Frage wurde bearbeitet).
Nyi
Wenn Ihr Dateisystem Hardlinks unterstützt und Sie in dasselbe Dateisystem klonen, benötigt clone -l keinen Speicherplatz mehr, da alle Objekte fest verknüpft werden. Sie benötigen jedoch Platz für die Kasse, wie andere angemerkt haben.
Neil Mayhew
1
Wenn Ihr nacktes Repository 20 GB Speicherplatz beansprucht, wie viel mehr würde der Arbeitsbaum benötigen? Hast du wirklich so viel Platz?
ADTC

Antworten:

113

Hinweis : Ich habe dies in einem sehr einfachen 1-Commit-Repository getestet . Überprüfen Sie dies noch einmal, lesen Sie die Manpages und seien Sie immer froh, dass Sie ein Backup erstellt haben, bevor Sie den Ratschlägen folgen, die Sie auf StackOverflow gefunden haben. (Sie sichern, richtig?)

So konvertieren Sie ein --bareRepository in ein nicht nacktes:

  1. Erstellen Sie einen .gitOrdner in der obersten Ebene Ihres Repositorys.
  2. Verschieben Sie die Repository-Verwaltungselemente ( HEAD branches config description hooks info objects refsusw.) in das .gitsoeben erstellte.
  3. Führen Sie git config --local --bool core.bare falsediese Option aus, um das lokale Git-Repository in ein nicht nacktes zu konvertieren.
  4. (über einen Kommentar von Tamás Pap ) Nach Schritt 3 sehen Sie, dass Sie sich in einem Zweig befinden master(oder in welchem ​​Hauptzweig sich auch immer befindet) und alle Ihre Dateien gelöscht und der Löschvorgang inszeniert wird. Das ist normal. Einfach manuell auschecken masteroder a git reset --hard, und fertig.
  5. (to resolve Ausgabe berichtete von Royi ) bearbeitet .git/configDatei hinzufügen Zeile fetch = +refs/heads/*:refs/remotes/origin/*nach url = <...>in [remote "origin"]Abschnitt. Andernfalls git fetchwerden origin/masterdie Zweige anderer Herkunft nicht angezeigt.

Diese Schritte sind in der entgegengesetzten Richtung von dieser Frage , „git-convert normal entblößen Repository“ - insbesondere Notiz dieser Antwort , die besagt , dass die obigen Schritte (in, nehme ich an, entweder Richtung) ist verschieden von einem tun git-clone. Ich bin mir nicht sicher, ob das für Sie relevant ist, aber Sie haben es git clonein der Frage erwähnt.

simont
quelle
2
Ich habe alles geschrieben, aber wenn ich Dateien pushe, werden sie nicht angezeigt. Was könnte es sein (ich habe auch leugnenCurrentBranch auf Ignorieren umgestellt)?
Royi
Vielen Dank! Eines Tages kam ich zur Arbeit und stellte fest, dass mein Haupt-Repo - von dem ich anderswo mehrere Arbeitsbäume hatte - sich als "nackt" meldete. Alle anderen Arbeitsbäume waren in Ordnung. Ich hatte keine Ahnung, wie ich ungehindert werden sollte, fand aber diese Antwort und es funktionierte großartig.
Davidbak
17

Ich hatte ein etwas anderes Szenario:

Lösung:

  • Klonen Sie ein nacktes Repo in diesem Inhalt in einem .gitVerzeichnis:
    git clone --bare https://github.com/user/project .git
  • Markieren Sie es als nicht nacktes Repo:
    git config --local --bool core.bare false
  • Zurücksetzen des Index (andernfalls wird angenommen, dass alles gelöscht wurde, da ein .git nacktes Repo keine Datei ' index' enthält.) Damit wird der Index
    git reset HEAD -- .
    wiederhergestellt .git/index.

Ich habe ein nacktes Repo effektiv in ein nicht nacktes verwandelt und dabei den Inhalt beibehalten, den ich zuvor erhalten hatte.
Das vollständige Skript, das ich seit Jahren verwende, umfasst die folgenden Schritte:

cd /path/to/current/worktree

# That creates a .git directly at the right place
git clone --bare /url/of/repo .git

# restore the link between the local repo and its upstream remote repo
git config --local --bool core.bare false
git config --local remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
git fetch origin
git branch -u origin/master master

# reset the index (not the working tree)
git reset HEAD -- .

Ich akzeptiere jedoch, dass die akzeptierte Lösung (mit dem von ADTC hinzugefügten hilfreichen git resetSchritt ) einfacher ist.

VonC
quelle
Es ist auch erwähnenswert, dass, wenn das nackte Repository auf einem Computer mit unterschiedlichen Zeilenenden erstellt wurde, möglicherweise auch nach Ausführung dieser Schritte noch geänderte Dateien angezeigt werden. Ich glaube das ist normal; git versucht die Linefeeds zu reparieren. Nicht sicher warum.
Juno Woods
Sie haben also ein GitHub-Repo im Grunde genommen als bare geklont, auf non-bare umgestellt, die gesamte Datei manuell aus Ihrem "non-repo" abgelegt und den Index zurückgesetzt? Wie unterscheidet es sich davon, das Repo überhaupt als nicht nackt zu klonen? Der nicht nackte Klonprozess überprüft ohnehin alle Dateien. Und wenn Sie wirklich wollen, können Sie einfach die ausgecheckten Dateien durch die aus Ihrem "Non-Repo" ersetzen.
ADTC
@ADTC Das Ziel ist es, einen .gitUnterordner in einem Arbeitsbaum (von dem Sie wissen, dass er Ihr Repo ist) zu erhalten, der ursprünglich aus einem Archiv (Nicht-Git) erstellt wurde. Ich hätte ein nicht nacktes Repo nicht auschecken können, da der Ordner, in dem ich das Auschecken durchgeführt habe, nicht leer ist. Das Nicht-Bare git clone --no-checkoutin einem Unterordner zu tun, hätte mich gezwungen, die .giteine Ebene nach oben zu verschieben. Durch einen bloßen Klon konnte ich den .gitUnterordner direkt dort erstellen, wo ich ihn haben wollte. Sie können das Skript hier sehen: github.com/VonC/compileEverything/blob/…
VonC
"Ich hätte kein nicht nacktes Repo auschecken können, da der Ordner, in dem ich das Auschecken durchgeführt habe, nicht leer ist." Sie meinen, Sie haben einen Nicht-Git-Arbeitsbaum, der Änderungen enthält, die noch nicht festgeschrieben wurden, und Sie möchten ihn festschreiben, nachdem Sie ihn in einen Git-fähigen Arbeitsbaum konvertiert haben? Ja, ich denke, es funktioniert für einen solchen Anwendungsfall. Persönlich würde ich in einen leeren Ordner klonen und die beiden zuerst vergleichen (mit einem externen Tool). Aber das bin nur ich.
ADTC
@ADTC Nein: Ich habe keinen "Nicht-Git-Arbeitsbaum, der Änderungen enthält, die noch nicht festgeschrieben sind". Ich möchte nichts begehen. Was ich habe , ist ein genau funktionierender Baum eines Repos: Alles, was fehlt, ist sein .git. Ich bekomme das .gitdurch einen nackten Klon, ich verwandle diesen .gitOrdner in einen nicht nackten und mache einen git reset, um git klar zu machen, dass der Arbeitsbaum bereits da ist. Genau das macht github.com/VonC/compileEverything/blob/… .
VonC
11

So vereinfachen und kombinieren Sie die Informationen in den Antworten:

Es gibt drei Unterschiede, die ein nacktes Repo von einem normalen .git-Ordner unterscheiden:

  • core.bare wird in der Konfigurationsdatei auf true gesetzt
  • Indexdatei und Arbeitsbaum sind nicht vorhanden
  • Eine Standardreferenzspezifikation für die "Ursprungs" -Fernbedienung wird nicht generiert

Sie können Ihr Bare-Repo also einfach in den .git-Unterordner eines neuen Ordners verschieben.

mkdir clone
mv bare.git clone/.git

Core.bare ändern:

cd clone
git config --local --bool core.bare false

Fügen Sie eine Standard-Ursprungsreferenz hinzu, um dieselben Standardeinstellungen wie gewohnt zu erstellen git fetchund git pushauszuwählen:

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

Und generieren Sie die Indexdatei und den Arbeitsbaum:

git checkout master

Ich empfehle , die Dateien git checkoutnicht git resetzu generieren, falls sie versehentlich an der falschen Stelle eingegeben werden.

fuzzyTew
quelle
9

Bei der Frage des Originalplakats geht es darum, nicht genügend Platz zu haben, um die Dinge auf einfache Weise zu erledigen. Für diejenigen, die genug Platz haben, ist die Antwort viel einfacher:

git clone foo.git foo
Sarnold
quelle
Der Grund, warum ich dies vermeiden möchte, ist, wenn das Repo groß wird und der Git-Klon manchmal stirbt. Ich möchte eine Synchronisierung des Bare-Repo durchführen und es dann konvertieren.
Sridhar Sarnobat
@SridharSarnobat, dann erwägen Sie, die in der akzeptierten Antwort beschriebenen Aufgaben auszuführen : stackoverflow.com/a/10637882/377270 - Ich habe diese einzeilige Antwort hier eingefügt , damit Personen mit genügend freiem Speicherplatz die Dinge auf einfache Weise erledigen können.
Sarnold
6

Wenn Sie nur noch wenig Speicherplatz haben, ist das Erweitern des Arbeitsbaums durch Konvertieren in ein normales Repository ein Problem. Sie können jedoch den Inhalt eines Bare-Repos durchsuchen, ohne ihn zu konvertieren. Verwenden Sie dieses git cat-file -p <commit-sha>Commit, um den Baum anzuzeigen, auf den es verweist. Verwenden Sie git cat-file -p <blob-sha>diese Option , um den Inhalt der Datei anzuzeigen, auf die der Blob verweist. Verwenden Sie diese git show <sha>:pathOption, wenn sha entweder ein Commit oder ein Baum ist, um den Inhalt des Blobs im Pfad anzuzeigen.

William Pursell
quelle
1
Sie haben Recht, aber ich muss es bequemer durchsuchen (in einem Dateimanager über ssh). Ich muss also mit dem erhöhten Speicherplatz leben.
Nyi
1
Eigentlich ist das ein echtes Problem (+1). Arbeitsbäume belegen oft bis zur Hälfte des Speicherplatzes. Zum Teil, weil Git-Historien aggressiv komprimiert werden.
Jpaugh
3

cd in nacktes Repo und tun

  1. Entweder:
git config core.bare false
git reset --hard
  1. oder
git clone X.git X

(gibt dir reguläres Git Repo mit dem Namen X)

nPcomp
quelle
Dies ist die einfachste Lösung und ich kann 2019 bestätigen, dass sie funktioniert (der erste Ansatz).
Sridhar Sarnobat
Nur eine kleine Anmerkung, die ich vergessen hatte (gilt für alle Antworten): Sie müssen die Konfigurationsdatei bearbeiten, wenn Sie zum ersten Mal drücken, um die Remote-URL festzulegen.
Sridhar Sarnobat
2

Wenn es Ihnen nichts ausmacht, an einem anderen Arbeitsbaum zu arbeiten, dann

git worktree add ../repo2
cd ..
git status # now works fine

Bitte beachten Sie, dass dies kein Klon ist.

Boaz Nahum
quelle
Das ist großartig, nicht sicher, warum dies nicht weiter oben auf der Liste steht
Nickolai
0

Push-to-Deploy

Anstatt die nackte Fernbedienung in ein Standard-Repository zu konvertieren, können Sie das Post-Receive-Skript im Hooks-Verzeichnis verwenden, um das Repository in ein Bereitstellungsverzeichnis zu erweitern.

Hier ist ein gutes Beispiel für die Einrichtung von Push-to-Deploy

Zur Vereinfachung der Bezugnahme ist dies das Beispiel für den Skriptinhalt über den obigen Link. Es werden nur Pushs vom Zweig "master" in ein Verzeichnis mit dem Namen "deploy" bereitgestellt, das sich auf derselben Ebene befindet wie das übergeordnete Verzeichnis des Repositorys:

#!/usr/bin/env ruby
# post-receive

# 1. Read STDIN (Format: "from_commit to_commit branch_name")
from, to, branch = ARGF.read.split " "

# 2. Only deploy if master branch was pushed
if (branch =~ /master$/) == nil
    puts "Received branch #{branch}, not deploying."
    exit
end

# 3. Copy files to deploy directory
deploy_to_dir = File.expand_path('../deploy')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master`
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
Isaac Brown
quelle