In dieser Blogreihe werden wir uns mit dem Thema Git beschäftigen und damit, warum das Arbeiten mit Git oder mit einem ähnlichen Tool für Entwickler fast schon unumgänglich ist.

Die folgenden Informationen werden auch, jedoch um einiges ausführlicher, in unseren offiziell bei der SAP im Schulungskatalog gelisteten Kursen HOUI5, HOFIO und WDECPS behandelt.

Inhalt

Auf folgende Themen werden wir in unserer Blogereihe eingehen:

  • Einführung in die Welt von Git
  • Begrifflichkeiten und die wichtigsten Funktionen
  • SAPUI5-Entwicklung mit Hilfe von Git
    • Exkurs: LDAP-Anbindung und Git-Server-Anbindung an die SAP Cloud Platform

Zielsetzung

Unser Ziel ist es, dass man nach unserer Blogreihe die unten stehende Grafik interpretieren und mit Git die SAPUI5-Entwicklung optimieren kann.

Part 3 – Inhaltsverzeichnis

  1. Repository anlegen (GitHub und SCP)
  2. Git Pane in der WebIDE + die wichtigsten Funktionen
  3. Conflict Handling

Einen letzten Punkt haben wir noch in unserer dreiteiligen Blogreihe, nämlich die Verwendung von Git bei SAPUI5-Entwicklungen.

SAPUI5-Entwicklung

Ein jeder SAPUI5-Entwickler wird wahrscheinlich diesen Hinweis beim Importieren von bereits bestehenden SAPUI5-Apps aus dem ABAP-Repository schon mal gesehen haben:

Auch wenn man sonst noch nie was von Git gehört hat, wird man spätestens an dieser Stelle merken, dass es fast unabdingbar mit Git die Sourcen zu verwalten.

Aber wenn es um Git geht, stellt die SAP nicht nur diesen Hinweis zur Verfügung, sondern auch einen in die WebIDE integrierten Git Pane zur Verfügung.

Repository anlegen

Für unser Beispiel werden wir zwei Git Repositories anlegen, nämlich einmal in GitHub und in der SAP Cloud Platform. Unser Beispielprojekt ist nachher nur mit dem GitHub Repository verknüpft. Im Lizenzmodell für die WebIDE sind auch die Git Repositories in der SAP Cloud Platform inkludiert.

GitHub

In GitHub können wir private Repositories anlegen, aber auch Repositories in Organisationen, in denen ich eingeladen worden bin.

Man hat zurzeit zwei Varianten an Repositories:

Public Repositories

  • für alle zugänglich, die den Link zur Repository haben
  • jeder kann clonen
  • Schreibrechte kann man einschränken (Push-Requests)

Private Repositories

  • nur für Sie oder für die Organisation sichtbar (siehe Owner)
  • Innerhalb Ihrer Org. kann man eigene Teams verwalten, die je nach Rolle Lese- und Schreibrechte haben

Zusätzlich sollte man noch einen README-File anlegen lassen, welche als Startseite für den Repository dient und dem User grundlegende Informationen vom Repo. anzeigen soll.

Es besteht auch die Möglichkeit, bestimmte Files und Filetypen ignorieren und bekannte Lizenzmodelle hinzufügen zu lassen. (.gitignore)

Nach dem Klick auf „Create repository“ wird man auch gleich in den Repository Browser geleitet:

Auf alle einzelnen Möglichkeiten möchte ich hier nicht detailliert eingehen, weil diese Informationen eh schon überall im Internet zu finden sind.

Kurz zusammengefasst:

  • man kann Lese- und Schreibrechte an bestimmte Personen und Teams vergeben
  • Commits und Pull-Requests verfolgen
  • Auswertungen ansehen
  • in den Einstellungen von Security bis Benachrichtigungen alles einstellen

Was für uns in Zukunft jetzt wichtig ist, ist der Repository URL. Bei einem Clone müssen wir diese URL angeben, denn diese ist der Zeiger zu unserem Repository:

https://github.com/clouddnagmbh/blogrepo

SAP Cloud Platform

Im Subaccount in der SCP (SAP Cloud Platform) hat man links im Menü die Möglichkeit Repositorys zu verwalten. Wenn Sie diesen Menüpunkt nicht sehen, dann fehlen Ihnen wahrscheinlich die nötigen Berechtigungen.

Mit dem „New Repository“-Button können wir gleich einen Repository anlegen. Hier ist natürlich wichtig zu wissen, dass die Authentifizierung über die SCP erfolgt.

Nachdem wir einen Namen und Beschreibung vergeben haben, können wir noch bestimmen, dass unser Repository mit einem initialen leeren Commit angelegt werden soll.

Wenn wir die Details zu unserer Repository anschauen, dann können wir ein paar Informationen ablesen und direkt auch einige Funktionen ausführen.

Es besteht die Möglichkeit, wieder den Namen zu editieren, unserem Repository nur Leserechte zu geben, den Garbage Collector zu starten, aber auch unser Repository direkt in die WebIDE clonen zu lassen.

Zwei wichtige Links sieht man auch gleich, nämlich einen mit dem Zeiger auf unseren Repository (wichtig, wenn man clonen möchte) und einen für den Repository Browser (nichts anderes als ein Explorer).

Was für uns in Zukunft jetzt wichtig ist, ist der Repository URL. Bei einem Clone müssen wir diese URL angeben, denn diese ist der Zeiger zu unserem Repository:

https://git.eu2.hana.ondemand.com/<subaccount>/blogrepo

Entwicklung

In unserer WebIDE können wir an mehreren Stellen einen Git Repository clonen. Anbei eine Möglichkeit:

Alle Varianten würden im Endeffekt zu diesem Wizard führen:

Hier müssen wir unsere Repository URL einfügen. Zusätzlich könnte man eine Konfiguration für Gerrit, ein Review-System von Google, hinzufügen.

Nach einer erfolgreichen Authentifizierung und Clone sehen wir die geclonte Applikation in unserem Workspace:

Jedoch bringt uns das in unserem Fall noch nichts, weil unser Repository leer ist. Wir haben ja im zweiten Teil unserer Blogreihe gelernt, dass ein Entwickler der Erste sein muss, der quasi eine Rahmenapplikation deployed.

Also lösche ich vorerst das geclonte Projekt, lege eine neue SAPUI5-App an und mit Rechtsklick auf das Projekt lege ich ein neues lokales Git Repository an:

In einem Popup kann man den Benutzernamen und die Mailadresse hinterlegen, welche bei den Commits als Author eingetragen wird:

Der Hinweis, dass das nicht mehr geändert werden kann, stimmt hier nicht ganz. Über Project -> Project Settings -> Git Repository kann das ganze geändert werden.

Nach dem ich das lokale Git Repository angelegt habe, bekomme ich auch gleich die Information, dass ich einen Remote Repository anbinden soll:

Das machen wir auch gleich und tragen unseren bereits erstellen Remote Repository ein:

Da das Ganze im Grunde genommen nichts anderes ist, als das Zusammenführen von Local und Remote Repository, wird zuerst noch ein Fetch gemacht.

Wir öffnen direkt den integrierten Git Pane:

Wir können hier in einer grafischen Oberfläche verschiedene Funktionen ausführen:

  1. Wie wir im zweiten Teil unserer Blogreihe kennengelernt haben, könnte man hier auf die verschiedensten Funktionen (Fetch, Merge, Pull, …) zugreifen.
  2. Man sieht auf einem Blick um welchen Local Repository es sich handelt und man könnte neue Local Branches erstellen und zwischen diesen wechseln.
  3. Eine Liste der Änderungen seit dem letzten Commit.
  4. Alle Änderungen, die sich im Staging Area befinden, werden auch beim nächsten Commit mitgenommen. Also wenn ich Änderungen habe, die ich noch nicht veröffentlichen will, dann werde ich diese aus der Staging Area rausnehmen und somit beim nächsten Commit nicht mit den anderen teilen.
  5. Jeder Commit erfordert eine Beschreibung, wie zum Beispiel eine kurze Zusammenfassung meiner Änderungen.
  6. Die Möglichkeit für Commit und Push findet man ganz unten.

Symbole in der WebIDE

Initial Commit and Push

Wir haben einen Rahmenprojekt angelegt und sind der erste, der das Projekt auf den Remote Repository pusht:

Nach einem erfolgreichen Push-Request können wir die Sourcen am Repository Browser ansehen:

Nehmen wir jetzt an, dass wir diese Applikation nicht erstellt haben. Dann müssten wir genau an dieser Stelle einen Clone in unsere WebIDE vollziehen:

Bei einem Clone erhält unser Projekt in der WebIDE den Namen vom Remote Repository. Gleich daneben steht auch, auf welchem lokalen Branch wir gerade arbeiten:

Local Branch erstellen

Im Git Pane haben wir die Möglichkeit zu unserem standardmäßig erstellen „master“ Branch weitere Local Branches zu erstellen.

Man wählt die Quelle aus (kann auch ein Remote Branch sein) und benennt den zu erstellenden lokalen Branch (in unserem Fall „featureA“):

Nach dem Erstellen befinden wir uns auch schon direkt in dem Feature Branch. Man kann mithilfe des Drop-Downs auch wieder wechseln.

In unserem Feature Branch machen wir ein paar Änderungen, legen neue Views an und fügen ein Label in die View ein. Wir beschreiben die Änderungen dementsprechend und committen sie:

Wir sind mit unseren Feature Implementierungen fertig und möchten diese mit anderen Entwicklern teilen. Wir haben in unserem Git Pane einen Indikator, dass wir seit dem letzten Merge einen Commit gemacht haben:

Wir wechseln nun in den lokalen „master“ Branch und machen einen Merge mit unserem Feature Branch. Wir verbinden die zwei Datenstände miteinander und prüfen auf eventuelle Konflikte:

Nachdem der Merge (in unserem Fall) ohne Konflikte durchgelaufen ist, checken wir die Sourcen im „master“ Branch und sehen, dass die Änderungen aus unserem Feature Branch in unserem lokalen „master“ Branch gelandet sind:

Wir hätten unseren Feature Branch natürlich auch gleich mit dem Remote Branch zusammenführen können, aber so konnten wir schonmal sichergehen, dass es mit dem letzten „origin/master“ Branch, welche ja unserem lokalen „master“ Branch entsprochen hat, keine Konflikte gibt.

Das bringt den anderen Entwicklern jetzt noch nichts. Wir müssen diese Änderungen auch auf den Remote Repository pushen. Aber wie wir schon im zweiten Teil unserer Blogreihe gelernt haben, müssen wir vorher checken, ob die anderen auch schon Änderungen gemacht und am Remote Repository gepusht haben.

Ich bevorzuge an dieser Stelle einen Fetch. In der Zusammenfassung schaue ich mir auch an, ob und was andere Entwickler gemacht haben:

Wir sehen, dass sich am Remote Repository seit unserem letzten Fetch nichts getan hat, somit können wir beruhigt pushen:

Wenn wir jetzt in den Browser Repository wechseln, dann werden wir auch sehen, dass dort unsere Änderungen bzw. unsere Feature Entwicklung sichtbar ist:

Was man hier noch gut sieht ist, dass nur die Deltas ausgetauscht worden sind. Die nicht geänderten Files haben noch immer den letzten Status und auch die letzte Commit Beschreibung, weil wir selbst die anderen Files, auch wenn wir am Projekt was geändert haben, nicht manipuliert haben.

Conflict Handling

In unserem Fall war das jetzt ganz einfach, da kein anderer Entwickler uns in die Quere kommen konnte. Aber wie ein Konflikt aussehen würde, haben wir hier für Sie simuliert.

Ich habe mich umentschieden und in meiner WebIDE im Label doch einen anderen Text eingetragen:

Diese Änderung werde ich jetzt wie gewohnt in die Staging Area bringen und mit einer entsprechenden Beschreibung einen Commit durchführen:

Wir machen einen Fetch um zu sehen, ob andere Entwickler auch was gemacht haben:

Da sehen wir jetzt, dass ein anderer Entwickler auch etwas geändert hat. Vorerst kein Problem, das ist ja eine ganz normale Situation, da unser Entwicklungsteam groß ist.

Was für uns aber neu ist, ist dieser Indikator:

Das bedeutet wir haben einen Commit seit dem letzten Merge gemacht und auch am dazugehörigen Remote Repo. hat es einen Commit seither gegeben.

Wir machen jetzt einen Merge, um die zwei Datenstände miteinander zu vereinen und da bemerken wir, dass es Konflikte gibt:

Wir klicken auf „Resolve Conflicts“ und landen in einem grafischen Editor für das Beheben der Konflikte:

Hier sieht man die zwei Versionen einander gegenübergestellt und auch die Version, die nach unserer Konfliktbehebung entstehen würde.

Mit den Buttons rechts oben könnten wir auf die Schnelle sagen, ob wir unsere Änderungen oder die Änderungen vom Remote Repo. nehmen möchten. Hinter diesem grafischen Editor steht eigentlich nichts anderes als ein Code mit bestimmten Abschnitten und Markierungen, wo Konflikte aufgetreten sind:

Also könnte man im grafischen Editor die Konflikte lösen, aber auch im Code. Man würde hier genau diesen Abschnitt rausschmeißen, welchen man als veraltet empfindet.

Wenn wir alle Konflikte behoben haben, dann bleibt uns nichts anderes mehr übrig, als einen Commit zu machen, je nachdem wie viel Zeit wir für die Konflikten aufgewendet haben, wieder einen Fetch mit Merge zu machen und anschließend unseren Code zu pushen.

Bei einem Conflict Handling haben wir während dem Beheben auch nicht alle Funktionen zur Verfügung:

Wir können lediglich einen Fetch machen und uns den aktuellen Stand holen oder die bereits gemachten Änderungen zurücksetzen.

Nach einem Commit von unserer Fehlerbehebung sehen wir am Indikator, dass wir nun nicht einen Commit vor und auch gleichzeitig nach dem origin/master sind, sondern zwei Commits voraus. Einmal haben wir ja unser Label geändert und einmal einen Merge mit Konfliktbehebung (= erneuter Commit) gemacht.

Zusammenfassung

Jetzt steht uns nichts mehr im Wege! Wir haben gelernt, wie wir unsere Entwicklungen mit Git optimieren können und in diesem Bereich vor allem das Zusammenarbeiten mit anderen Entwicklern. Der nächste und letzter Teil unserer Blogreihe, nämlich ein Exkurs von Martin Koch verfasst und präsentiert, wird nächste Woche veröffentlicht.