21. November 2013

Branches von Remote-Tracking-Branches ableiten, Clone, Push/Pull

Remote-Tracking-Branches wie origin/feature_ab dienen ausschließlich dazu, den Zustand im Remote-Repository lokal abzubilden. Wenn Sie in einen Remote-Tracking-Branch wechseln, wird git den jeweiligen Commit im detached HEAD-Modus auschecken, in dem Sie diesen Stand ansehen können, jedoch keine Änderungen daran vornehmen können:

$ git checkout origin/feature_ab
Note: checking out 'origin/feature_ab'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

Für die Arbeit an Remote-Branches ist daher zunächst ein lokaler Branch von dem Remote-Tracking-Branch abzuleiten:

$ git checkout -b feature_ab origin/feature_ab

Die Angabe des Remote-Tracking-Braches als Ausgangspunkt kann dabei entfallen, da ein gleichnamiger Remote-Tracking-Branch automatisch verwendet wird:

$ git checkout -b feature_ab
Branch feature set up to track remote branch feature_ab from origin.
Switched to a new branch 'feature_ab'

$ git branch -vv
* feature_ab          fc3ed27 [origin/feature_ab] some commit

git clone

Ein Repository kann mit git clone lokal repliziert werden:

$ git clone <url> [<directory>]

Dabei erfolgen automatisch folgende Schritte:

Fetch + Merge = Pull

Erfolgen Änderungen in dem Remote-Repository, werden mit git fetch die Remote-Tracking-Branches aktualisiert:

$ git fetch
From github.com:ralfebert/testrepo
  a4452e9..c8c8187  master         -> origin/master

Danach können die Änderungen in den lokalen Arbeits-Branch gemergt werden:

$ git checkout master
$ git merge origin/master

Die Operationen git fetch + git merge erfolgen mit git pull in einem Schritt:

$ git pull

Konflikte beim Push

Beim Push zum Remote-Repository muss der letzte Commit in dem Remote-Branch ein Vorgänger der zu pushenden Commits sein. Wenn zwischenzeitlich in dem Ziel-Repository Änderungen erfolgt sind, erhält man folgenden Fehler:

error: remote 'refs/heads/master' is not an ancestor of
local  'refs/heads/master'.
Maybe you are not up-to-date and need to pull first?
error: failed to push to 'git://bob@server/path/to/repo.git'

In diesem Fall müssen die Änderungen mit fetch + merge bzw. pull geholt und in den lokalen Branch gemergt werden, um dann den gemergten Stand zu übertragen.

Upstream-Branches und push.default

Sofern keine explizite Angabe erfolgt, welcher Branch übertragen werden soll, werden aktuell alle gleichnamigen Branches gepusht. Dieses Verhalten von git push wird sich in Git 2.0 ändern.

Zukünftig wird nur noch der aktive Branch übertragen. Der zugehörige Remote-Branch wird für jeden Branch explizit als Upstream konfiguriert und Branch-Namen müssen gleichnamig sein, d.h. master wird immer zu <remote>/master gepusht.

Es empfiehlt sich, dieses vereinfachte Verhalten bereits jetzt zu aktivieren:

git config --global push.default simple

Wird nun beim Aufruf von git push der zu übertragende Branch nicht angegeben, wird der aktive Branch zu seinem explizit konfigurierten Upstream-Branch gepusht:

$ git branch -avv
* master                  03d2cae some commit

$ git push origin master  # master -> origin/master

$ git branch -avv
* master                  03d2cae [origin/master] some commit
                          #        ^^^ Upstream

$ git push                # aktiver Branch master -> Upstream Branch origin/master

Aufgaben

  1. Rufen Sie http://github.com/ralfebert/testrepo auf und klonen Sie das Projekt lokal (zwischenzeitlich wurden die Feature-Branches entfernt, so dass es im Remote-Repository nur noch einen master-Branch gibt).
  2. Nehmen Sie lokal in master einen oder mehrere Commits vor und senden Sie diese zum Server. Beseitigen Sie dabei ggf. auftretende Konflikte mit Commits der anderen Schulungsteilnehmer.
  3. Mergen Sie Änderungen, die zwischenzeitlich im Remote-Repository erfolgen, in Ihren lokalen Branch.
  4. Erstellen Sie einen lokalen Branch und pushen Sie diesen in das Remote Repository.
  5. Mergen Sie einen Remote-Branch eines Kollegen in Ihren lokalen master-Branch und pushen Sie diesen.