Git onder Windows met remote repositories

In een vorig artikel hebben we gezien dat we Git kunnen gebruiken om met verschillende versies van bestanden te werken. Die verschillende versies werden lokaal bijgehouden. Git is echter een gedistribueerd versie beheersysteem. In dit artikel bekijken we hoe we dat lokale systeem kunnen koppelen aan een centrale repository.

Een centrale repository

Wanneer verschillende ontwikkelaars samenwerken met behulp van Git, zullen ze hun eigen lokale repository hebben. Die lokale repositories zijn, zoals de naam al doet vermoeden, niet met elkaar verbonden. De wijzigingen van de verschillende ontwikkelaars zullen alleen maar samengevoegd kunnen worden wanneer er op één of andere manier een link wordt gelegd. Daarvoor dient de centrale repository. Elke ontwikkelaar zal de wijzigingen in de eigen repository doorsturen naar de remote repository.

Git maakt hierbij onderscheid tussen bare en development repositories. De repository die we in het vorige artikel hebben gezien was een development repository. Naast de eigenlijke repository was er ook een working directory. Hierin stonden de bestanden waarmee de ontwikkelaar aan het werken was.

Een remote repository is een bare repository. Er is geen working directory, alleen een repository. Op de remote repository wordt er nooit rechtstreeks gewerkt. De inhoud moet altijd gekopieerd worden naar een development repository voordat de bestanden gebruikt kunnen worden.

We kunnen we inhoud van een development repository kopiëren naar een nieuwe bare repository via git clone –bare.

We kunnen ook een nieuwe bare repository maken met behulp van git init –bare. In dit voorbeeld maken we een remote repository aan op de eigen machine in c:\xampp\repo:

$ mkdir /c/xampp/repo

$ git init --bare /c/xampp/repo
Initialized empty Git repository in c:/xampp/repo/

Een lokale repository koppelen aan een remote repository

Om vanuit de lokale repository te werken met een remote repository, zullen we eerst een alias moeten definiëren voor de remote repository. Volgens de conventie krijgt die de naam “origin”:

$ git remote add origin /c/xampp/repo

Vervolgens kunnen we de inhoud van de master branch uploaden naar de remote repository:

$ git push origin master
Counting objects: 32, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (24/24), done.
Writing objects: 100% (32/32), 2.92 KiB, done.
Total 32 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (32/32), done.
To c:/xampp/repo
 * [new branch]      master -> master

Stel dat we nu een tweede ontwikkelaar (Marieke) in een eigen lokale git repository willen laten werken. Deze repository zal de bestanden van de remote bevatten. We kunnen dit doen via het git clone commando:

$ mkdir /c/xampp/marieke

$ cd /c/xampp/marieke

$ git clone /c/xampp/repo/
Cloning into 'repo'...
done.

$ cd repo

$ ls
index.html  tweede.html

Marieke heeft een kopie gekregen van de bare (remote) repository. Door een clone te maken is de alias origin ook meteen gedefinieerd:

$ git remote show origin
* remote origin
  Fetch URL: c:/xampp/repo/
  Push  URL: c:/xampp/repo/
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

Marieke kan nu een derde bestand toevoegen, het lokaal committen en vervolgens uploaden naar de remote repository:

$ vi derde.html

$ git add derde.html

$ git commit -a
[master 7212d7a] Derde bestand toegevoegd
 1 file changed, 1 insertion(+)
 create mode 100644 derde.html

$ git push
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 328 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To c:/xampp/repo/
   ed2c927..7212d7a  master -> master

Joske kan de gegevens ophalen (directory c:\xampp\ontwikkeling):

$ cd /c/xampp/ontwikkeling

$ git pull origin master
From c:/xampp/repo
 * branch            master     -> FETCH_HEAD
Updating ed2c927..7212d7a
Fast-forward
 derde.html | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 derde.html

$ ls
derde.html  index.html  tweede.html

Joske heeft nu dezelfde bestanden als Marieke. We hadden het git pull commando voor Joske kunnen vereenvoudigen door een koppeling te maken tussen de eigen master en de remote master:

$ git branch --set-upstream master origin/master
Branch master set up to track remote branch master from origin.

Vanaf nu volstaat git pull om gegevens van origin/master te kopiëren naar de lokale master

Conflicten in de remote repository

Stel dat Joske en Marieke allebei iets wijzigen en vervolgens een push uitvoeren. We zullen eerst Joske een extra bestand laten toevoegen en het pushen naar de remote repository. Marieke doet vervolgens een aanpassen en probeert ook een push uit te voeren.

$ vi joske.html

$ git add joske.html

$ git commit
[master 671cf1e] Joske toegevoegd
 1 file changed, 1 insertion(+)
 create mode 100644 joske.html

jef@PC00 /c/xampp/ontwikkeling (master)
$ git push
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 345 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To c:/xampp/repo
   7212d7a..671cf1e  master -> master

$ cd /c/xampp/marieke/repo/

$ vi marieke.html

$ git add marieke.html

$ git commit
[master ae6ef7d] Marieke toegevoegd
 1 file changed, 1 insertion(+)
 create mode 100644 marieke.html

$ git push
To c:/xampp/repo/
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'c:/xampp/repo/'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Er wordt aangeraden om een ‘git pull’ te gebruiken. Het mergen moet lokaal bij Marieke gebeuren. Daarom moet de nieuwe situatie eerst worden opgehaald bij de centrale repository voordat we de gemergede bestanden kunnen uploaden.

Het git pull commando bestaat eigenlijk uit twee delen: git fetch en git merge. Om te laten zien wat die twee stappen doen, zullen we ze afzonderlijk uitvoeren:

$ git fetch
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From c:/xampp/repo
   7212d7a..671cf1e  master     -> origin/master

$ ls
derde.html  index.html  marieke.html  tweede.html

$ git merge origin/master
Merge made by the 'recursive' strategy.
 joske.html | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 joske.html

De git fetch heeft nog niets in de working directory gezet. In feite worden de bestanden in de lokale versie van origin/master gezet; Het git merge commando voegt de huidige branch samen met de lokale kopie van origin/master. Wanneer we de tree opvragen, zien we wat er gebeurd is:

$ git log --graph --oneline
*   b413f71 Merge remote-tracking branch 'origin/master'
|\
| * 671cf1e Joske toegevoegd
* | ae6ef7d Marieke toegevoegd
|/
* 7212d7a Derde bestand toegevoegd
*   ed2c927 Merge branch 'bugs/jv-001'
|\
| * ae50e72 Commentaar toegevoegd
* | 0df5807 uitbreiding kennismaking
* |   3a3f8f5 Merge branch 'bugs/jv-001'
|\ \
| |/
| * 207c020 Een tweede bestand toegevoegd (oplossing bug jv-001)
* | 29cb984 Kennismaking toegevoegd
|/
* 2046b2d Volgende versie begonnen
* 16dd1af Een titel van gemaakt
* a77cf20 Titel toegevoegd
* a1a94b2 Head tags toegevoegd
* a15f446 Eerste versie van index.html

Een wijziging in de centrale repository is in feite hetzelfde als een wijziging in een branch. En net zoals we een lokale branch kunnen samenvoegen met de master, kunnen we dat ook met een remote repository doen.

Wanneer Marieke vervolgens een git push uitvoert, zal haar versie op de centrale repository terecht komen:

$ git push
Counting objects: 7, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 506 bytes, done.
Total 5 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
To c:/xampp/repo/
   671cf1e..b413f71  master -> master

En wat met een “echt” conflict?

Het vorige conflict kon opgelost worden door Git. Er moest een extra bestand van Joske toegevoegd worden aan de bestanden van Marieke. Maar wat wanneer Git het probleem niet kan oplossen.

In de centrale repository staat er nu een bestand Marieke.html. Stel dat Joske in zijn eigen repository ook een bestand Marieke.html aanmaakt, het commit en de bestanden vervolgens probeert te pushen naar de remote repository?

$ cd /c/xampp/ontwikkeling/

$ vi marieke.html

$ git add marieke.html

$ git commit
[master d7fed51] Een Marieke toegevoegd door Joske
 1 file changed, 1 insertion(+)
 create mode 100644 marieke.html

$ git push
To c:/xampp/repo
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'c:/xampp/repo'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

$ git pull
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 5 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
From c:/xampp/repo
   671cf1e..b413f71  master     -> origin/master
Auto-merging marieke.html
CONFLICT (add/add): Merge conflict in marieke.html
Automatic merge failed; fix conflicts and then commit the result.

De git pul lukt niet omdat er conflicten zijn. Wanneer we het bestand marieke.html bekijken, zien we dat we hier een klassiek conflict bestand hebben.

<<<<<<< HEAD
Joske
=======
Marieke
>>>>>>> b413f71f32ab87beed6bc3ef0b0cfa4e13c5538f

We kunnen de noodzakelijke aanpassingen doen en het aangepaste bestand uploaden:

$ git commit -a
[master 540f4f5] Merge branch 'master' of c:/xampp/repo(opgeloste conflicten)

$ git push
Counting objects: 8, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 582 bytes, done.
Total 5 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
To c:/xampp/repo
   b413f71..540f4f5  master -> master

We zien hier weer dat conflicten op dezelfde manier worden opgelost als bij een lokaal merge conflict tussen twee branches.

Github als centrale repository

Github is een centrale repository op Internet die gratis mag gebruikt worden voor (openbare) Open source projecten. Vanaf het moment dat je een account hebt aangemaakt, kun je een nieuwe repository maken.

image

Vul een naam in voor de repository en eventueel een omschrijving. Wanneer je een README bestand aanmaakt, kun je de repository gemakkelijk clonen naar je lokale machine. Je hebt alleen de URL nodig van de repository. Voor de rest kun je het commando gebruiken dat ook geldt voor een remote repository op het file system:

$ git clone https://github.com/JoskeV/testgit.git
Cloning into 'testgit'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.

 

Wanneer we aanpassingen doen, kunnen we die “pushen” naar de github repository. Het enige verschil met een remote repository op het file system is dat er een gebruikersnaam en een paswoord zullen worden gevraagd:

$ vi test.html

$ git add test.html

$ git commit
[master 524594f] Een eerste bestand
 1 file changed, 1 insertion(+)
 create mode 100644 test.html

$ git push
Username for 'https://github.com': JoskeV
Password for 'https://JoskeV@github.com':
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 296 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/JoskeV/testgit.git
   8ade287..524594f  master -> master

Wanneer je nu de github repository bekijkt, zul je zien dat het bestand test.html op de github server staat.

Plaats een reactie

Deze site gebruikt Akismet om spam te bestrijden. Ontdek hoe de data van je reactie verwerkt wordt.