Firedrill: Erstellen Sie Github (oder jedes andere zentrale) Repository aus Entwicklerklonen neu

Lesezeit: 8 Minuten

Benutzeravatar von Thorbjørn Ravn Andersen
Thorbjørn Ravn Andersen

Angenommen, Sie haben ein Szenario mit einem zentralen Master-Git-Repository, aus dem Entwickler und CI-Engines klonen. Das heißt, sehr nah an einem traditionellen, nicht verteilten Versionskontrollsystem-Setup, mit einem zentralen Hub und vielen Knoten. Dies kann ein Cloud-Dienst wie Github (Gitlab/Savannah/Azure usw.) oder eine Synology mit Git-Server oder ein anderes internes Setup sein.

Nehmen wir nun an, dass der Server gestohlen oder vom Blitz getroffen wurde oder etwas anderes, was dazu führen würde, dass das zentrale Repository mit all seinen zentralisierten Backups verschwunden ist. Alles, was Sie noch haben, sind die verschiedenen Klone, und glücklicherweise wurde einer davon vollständig aktualisiert, also erstellen Sie einen leeren Git-Repository-Ersatzserver, der als zukünftiges zentrales Repository verwendet werden soll, und machen sich an die Arbeit an dem Klon.

Der vollständig aktualisierte Klon kennt alle “remotes/origin”-Zweige mit “git branch -a”, hat aber nur einen einzigen lokalen Zweig. (Das ist es, was mich beunruhigt – der Verlust von Zweiginformationen).

Was wären die Schritte, um ein neues zentrales Git-Repository wiederherzustellen, das sich in irgendeiner Weise wie das alte verhält, Zweige und alles?

Benutzeravatar von CB Bailey
CB Bailey

Erstellen Sie einfach ein leeres Repository und führen Sie vom vollständig aktualisierten Klon aus Folgendes aus:

git remote add new-origin url://to/new/origin

git push --tags new-origin refs/remotes/origin/*:refs/heads/*

Wenn der neue Ursprung dieselbe URL wie der ursprüngliche hat, müssen Sie natürlich darauf achten nicht vom Ursprung abrufen.

  • Das sollte es genau tun. In jedem Fall können Sie jederzeit einen lokalen Checkout des Remote-Zweigs durchführen, den Sie haben, und einen “git push origin HEAD” ausführen.

    – Carl-Eric Menzel

    22. August 2012 um 11:42 Uhr

Benutzeravatar von VonC
VonC

Installieren Sie bitte zuerst kein Gitosis: Nehmen Sie die neueste Version V3+ Gitolitein viel vollständiger Autorisierungsschicht: siehe “Gitosis vs Gitolite?” und “Warum brauchen Sie Gitosis oder Gitolite?”.

Zweitens verlieren Sie keine Verzweigungsinformationen.

Hier ist ein anderer Ansatz für das gleiche Problem, länger, aber der zeigt, wie Sie immer noch alle Zweige behalten.

Jeder Ihrer Clone hat möglicherweise nicht alle lokalen Zweige, aber alle diese Zweige befinden sich immer noch im Remote-Namespace dieser Klone, da sie aus demselben (jetzt verschwundenen) “zentralen” Repo geklont wurden.

Sobald Sie eines dieser Repos (als Bare Repo) auf den neuen zentralen Server geklont haben, brauchen Sie es nur noch ein wenig aufzuräumen, und Sie können es als Ihr neues gesegnetes Repo referenzieren.

Hinweis: Wenn Sie von Ihrem Server aus nicht auf ein lokales Repo zugreifen können, bündeln Sie dieses lokale Repo und kopieren Sie die eines Datei, die dieses Bundle darstellt, zurück auf Ihren Server: Sie können aus diesem Bundle klonen.
Sehen “git bundle: Bundle-Tags und Heads”, um das Bundle richtig zu erstellen.


Kurzfassung

# Let's re-create a bare "blessed" repo on the server
git clone --mirror /path/to/a/local/repo repo.git
# or git clone --mirror /path/to/repo.bundle repo.git

# restore the local branches
remote=origin ; for brname in `git branch -r | grep $remote | grep -v HEAD | awk '{gsub(/[^\/]+\//,"",$1); print $1}'`; do git branch --set-upstream $brname  $remote/$brname ; done

# delete the remotes branches
# (your blessed repo doesn't track anything)
remote=origin ; for brname in `git branch -r | grep $remote | grep -v HEAD | awk '{gsub(/[^\/]+\//,"",$1); print $1}'`; do git branch -r -d origin/$brname ; done

# delete the remote 'origin'
# Not needed for your blessed repo
git remote rm origin

# Let's make sure master is the current branch
# for that bare repo:
git symbolic-ref HEAD refs/heads/master

Das ist es. Bereit zu gehen.


Langversion (Demo)

Lassen Sie uns ein Repo mit 4 Zweigen erstellen: master, b1, b2, b3jeweils mit eigenen Dateien:

C:\Users\VonC\prog\git\tests>mkdir c
C:\Users\VonC\prog\git\tests>cd c
C:\Users\VonC\prog\git\tests\c>git init r1
Initialized empty Git repository in C:/Users/VonC/prog/git/tests/c/r1/.git/
C:\Users\VonC\prog\git\tests\c>cd r1
C:\Users\VonC\prog\git\tests\c\r1>echo m > m.txt && git add . && git commit -m "first commit"
[master (root-commit) 1ffe5c1] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 m.txt

C:\Users\VonC\prog\git\tests\c\r1>git checkout -b b1
Switched to a new branch 'b1'
C:\Users\VonC\prog\git\tests\c\r1>echo f1 > f1.txt && git add . && git commit -m "f1 in b1"
[b1 1e64d01] f1 in b1
 1 file changed, 1 insertion(+)
 create mode 100644 f1.txt

C:\Users\VonC\prog\git\tests\c\r1>git checkout -b b2 master
Switched to a new branch 'b2'
C:\Users\VonC\prog\git\tests\c\r1>echo f2 > f2.txt git add . && git commit -m "f2 in b2"
[b2 4462b8f] f2 in b2
 1 file changed, 1 insertion(+)
 create mode 100644 f2.txt

C:\Users\VonC\prog\git\tests\c\r1>git checkout -b b3 master
Switched to a new branch 'b3'
C:\Users\VonC\prog\git\tests\c\r1>echo f3 > f3.txt && git add . && git commit -m "f3 in b3"
[b3 7ada753] f3 in b3
 1 file changed, 1 insertion(+)
 create mode 100644 f3.txt

Wenn ich jetzt klonen r1 hinein r2und r2 hinein r3Jawohl, r3 würde Zweiginformationen verlieren:

C:\Users\VonC\prog\git\tests\c>git clone r1 r2
Cloning into 'r2'...
done.

C:\Users\VonC\prog\git\tests\c>git clone r2 r3
Cloning into 'r3'...
done.

C:\Users\VonC\prog\git\tests\c>cd r3

C:\Users\VonC\prog\git\tests\c\r3>git br -a
* b3
  remotes/origin/HEAD -> origin/b3
  remotes/origin/b3

Aber in Ihrem Fall sind die meisten Repos da draußen das direkte Ergebnis eines Klons aus dem gesegneten Repo.

r2 hat alle notwendigen Filialen (eine lokale, 4 Remote-Tracking-Zweigeda es keine “lokalen Tracking-Zweige” gibt):

C:\Users\VonC\prog\git\tests\c\r2>git br -a
* b3
  remotes/origin/HEAD -> origin/b3
  remotes/origin/b1
  remotes/origin/b2
  remotes/origin/b3
  remotes/origin/master

Wenn ich kann clone --mirror r2 in ein bloßes Repo r4ich werde noch alle Zweige bekommen.
Siehe „Was ist der Unterschied zwischen git clone --mirror und git clone --bare” warum.

C:\Users\VonC\prog\git\tests\c>git clone --mirror r2 r4
Cloning into bare repository 'r4'...
done.

C:\Users\VonC\prog\git\tests\c>cd r4

C:\Users\VonC\prog\git\tests\c\r4>git br -a
* b3
  remotes/origin/HEAD
  remotes/origin/b1
  remotes/origin/b2
  remotes/origin/b3
  remotes/origin/master

Seine Fernbedienung zeigt noch auf r2

VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:b3)
$ git remote -v
origin  C:/Users/VonC/prog/git/tests/c/r2 (fetch)
origin  C:/Users/VonC/prog/git/tests/c/r2 (push)

Aber das ist nicht mehr nötig.
Stellen wir sicher r2 (oder r1 übrigens) ist nicht mehr zugänglich:

VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:b3)
$ cd ..
VonC@HOSTNAME ~/prog/git/tests/c
$ mv r1 r1.old
VonC@HOSTNAME ~/prog/git/tests/c
$ mv r2 r2.old
VonC@HOSTNAME ~/prog/git/tests/c
$ cd r4

Jetzt können wir Stellen Sie die lokalen Zweige wieder herindem Sie sie auf die Remote-Tracking-Zweige verweisen:
Siehe “Alle Remote-Git-Zweige als lokale Zweige verfolgen”:

VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:b3)
$ remote=origin ; for brname in `git branch -r | grep $remote | grep -v HEAD | awk '{gsub(/[^\/]+\//,"",$1); print $1}'`; do git branch --set-upstream $brname  $remote/$brname ; done
Branch b1 set up to track remote ref refs/remotes/origin/b1.
Branch b2 set up to track remote ref refs/remotes/origin/b2.
Branch b3 set up to track remote ref refs/remotes/origin/b3.
Branch master set up to track remote ref refs/remotes/origin/master.

Lasst uns machen master der Standard-Zweig für dieses Bare-Repo:
Siehe „Git: Korrekte Methode zum Ändern von Active Branch in einem Bare-Repository?“ und „Wie ändere ich eine Git-Remote HEAD auf etwas anderes hinweisen als „master“”.

VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:b3)
$ git symbolic-ref HEAD refs/heads/master
VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:master)

Alles, was sich auf ‘origin‘ wird nicht mehr benötigt.
Lassen Sie uns die Remote-Tracking-Zweige loswerden:
Siehe „Zweige löschen aufgelistet von git branch -a” und “Entfernte Branches löschen?”

VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:master)
$ remote=origin ; for brname in `git branch -r | grep $remote | grep -v HEAD | awk '{gsub(/[^\/]+\//,"",$1); print $1}'`; do git branch -r -d origin/$brname ; done
Deleted remote branch origin/b1 (was 1e64d01).
Deleted remote branch origin/b2 (was 4462b8f).
Deleted remote branch origin/b3 (was 7ada753).
Deleted remote branch origin/master (was 1ffe5c1).

Lassen Sie uns in Panik geraten und überprüfen, ob unsere lokalen Zweigstellen immer noch auf das verweisen, was wir gerade “gelöscht” haben:
(Siehe „Den neusten Commit jedes Branches in Git anzeigen“)

VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:master)
$ git br -v
  b1     1e64d01 f1 in b1
  b2     4462b8f f2 in b2
  b3     7ada753 f3 in b3
* master 1ffe5c1 first commit

Ja, alles gut.

  • Ich mag die Änderung, die es Gitolite ermöglicht, dass derselbe Benutzer mehrere Schlüssel hat.

    – Thorbjørn Ravn Andersen

    24. Mai 2013 um 7:59 Uhr

1429630cookie-checkFiredrill: Erstellen Sie Github (oder jedes andere zentrale) Repository aus Entwicklerklonen neu

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

Privacy policy