Repositories kombinieren

posted by Steve Losh on November 17, 2009

Der letzte Tipp von Thomas decomposing repositories weckte bei mir das Bedürfnis, das Gegenteil zu beschreiben: Die Kombination von zwei unabhängigen Repositories in ein gemeinsames.

Wir nehmen an Sie arbeiten an einem Projekt. Der Code liegt in project und die Dokumentation in docs. Sie stellen fest, dass es praktischer wäre die beiden Teile nur in einem Repository zu haben. So hätte jeder der ihren Code klont auch die dazugehörige Dokumentation.

Sie könnten einfach ein neues Repository erzeugen und alle Dateien hinein kopieren. Dies würde aber den Verlust des Änderungsverlaufes bedeuten. Lassen Sie uns anschauen, wie wir die beiden unabhängigen Repositories zusammenführen können.

Erzeugen Sie das neue, kombinierte Repository

Als erstes erzeugen wir das neue Repository, das alles beinhalten wird:

$ ls
total 24
drwxr-xr-x  5 sjl   170B Nov 17 19:56 docs
drwxr-xr-x  4 sjl   136B Nov 17 19:58 project

$ mv project project-code

$ hg init project

$ ls
total 24
drwxr-xr-x  5 sjl   170B Nov 17 19:56 docs
drwxr-xr-x  3 sjl   102B Nov 17 20:04 project
drwxr-xr-x  4 sjl   136B Nov 17 19:58 project-code

Wir haben project in project-code umbenannt, damit das neue Projekt in project liegen kann.

Jedes Repository vorbereiten

Wir wollen wohl meistens nicht einfach alles zusammen in den Hauptordner werfen. Lassen Sie uns daher erst ein wenig aufräumen. Zunächst verschieben wir alles im ursprünglichen project Repository (jetzt project-code) in den src/ Ordner:

$ cd project-code

$ mkdir src

$ mv * src
mv: rename src to src/src: Invalid argument

$ ls
total 0
drwxr-xr-x  3 sjl   102B Nov 17 20:08 src

$ hg addremove --similarity 100
removing myproject.py
adding src/myproject.py
recording removal of myproject.py as rename to src/myproject.py (100% similar)

$ hg commit -m 'Move the code into the src/ directory.'

Nun machen wir das gleiche im docs Repository:

$ cd ../docs

$ mkdir docs

$ mv * docs
mv: rename docs to docs/docs: Invalid argument

$ ls
total 0
drwxr-xr-x  4 sjl   136B Nov 17 20:11 docs

$ hg addremove --similarity 100
removing LICENSE
removing README
adding docs/LICENSE
adding docs/README
recording removal of LICENSE as rename to docs/LICENSE (100% similar)
recording removal of README as rename to docs/README (100% similar)

$ hg commit -m 'Move the documentation into the docs/ directory.'

Beide Repositories verbinden

Nun da beide Repositories aufgeräumt sind, können diese mit pull ins neue project Repository übernommen werden:

$ cd ..

$ ls
total 24
drwxr-xr-x  4 sjl   136B Nov 17 20:12 docs
drwxr-xr-x  3 sjl   102B Nov 17 20:04 project
drwxr-xr-x  4 sjl   136B Nov 17 20:08 project-code

$ cd project

$ ls

$ hg pull --update ../project-code
pulling from ../project-code
requesting all changes
adding changesets
adding manifests
adding file changes
added 4 changesets with 4 changes to 2 files
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

$ ls
total 0
drwxr-xr-x  3 sjl   102B Nov 17 20:15 src

$ hg pull --force --update ../docs
pulling from ../docs
searching for changes
warning: repository is unrelated
adding changesets
adding manifests
adding file changes
added 3 changesets with 4 changes to 4 files (+1 heads)
not updating, since new heads added
(run 'hg heads' to see heads, 'hg merge' to merge)

$ ls
total 0
drwxr-xr-x  3 sjl   102B Nov 17 20:15 src

Wie Sie bemerken haben wir die Option --force genutzt. Diese sagt Mercurial das wir wirklich 2 unabhängige Repositories verbinden wollen.

Mergen der Repositories

Schauen Sie sich die Ausgabe des letzten ls Befehls an. Sie sehen das nur das src/ Verzeichnis angezeigt wird. Wir müssen nun die beiden Repositories mergen um sie endgültig zu kombinieren.

Um dies ein wenig klarer zu machen, werfen wir einen Blick auf den Grafen des neuen Repository:

$ hg glog
o  6 Move the documentation into the docs/ directory. (7 minutes ago by Steve Losh) tip
|
o  5 Add a LICENSE file. (22 minutes ago by Steve Losh)
|
o  4 Add a README file. (22 minutes ago by Steve Losh)

@  3 Move the code into the src/ directory. (10 minutes ago by Steve Losh)
|
o  2 Fix a bug. (21 minutes ago by Steve Losh)
|
o  1 Implement some basic functionality. (21 minutes ago by Steve Losh)
|
o  0 Start the project. (21 minutes ago by Steve Losh)

Sehen Sie die beiden unabhängigen Grafen? ChangeSet 0 bis 3 sind verbunden und ebenfalls 4 bis 6. Wir müssen nun die beiden Grafen zusammen mergen. Dies sollte problemlos möglich sein, da wir die Verzeichnisstruktur vorgängig aufgeräumt haben:

$ hg update 6
2 files updated, 0 files merged, 1 files removed, 0 files unresolved

$ hg merge 3
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

$ hg commit -m 'Combine the source and docs repositories.'

Schauen wir uns nun wieder den Grafen an:

$ hg glog
@    7 Combine the source and docs repositories. (37 seconds ago by Steve Losh) tip
|\
| o  6 Move the documentation into the docs/ directory. (11 minutes ago by Steve Losh)
| |
| o  5 Add a LICENSE file. (26 minutes ago by Steve Losh)
| |
| o  4 Add a README file. (27 minutes ago by Steve Losh)
|
o  3 Move the code into the src/ directory. (15 minutes ago by Steve Losh)
|
o  2 Fix a bug. (25 minutes ago by Steve Losh)
|
o  1 Implement some basic functionality. (25 minutes ago by Steve Losh)
|
o  0 Start the project. (26 minutes ago by Steve Losh)

$ ls
total 0
drwxr-xr-x  4 sjl   136B Nov 17 20:22 docs
drwxr-xr-x  3 sjl   102B Nov 17 20:22 src

Unsere beiden unabhängigen Repositories sind nun schön in einem samt ihrer ganzen Änderungsgeschichte zusammengeführt. Wir können nun die alten Repositories löschen und unser neues auf den öffentlichen Server publizieren.

Dieses Vorgehen ist besonders schön, da die Hashes der ChangeSets unverändert geblieben sind. Andere Personen die mit den alten Repositories arbeiten können so problemlos ihre Änderungen ins neue Repository mergen.

Was können Sie machen, wenn Sie bemerken: “Oh, vielleicht sollte die Dokumentation im gleichen Repository sein wie der Code?”