# Git commands involving models

When a user wants to compare or merge EMF models from the git command line interface, the operation is doing in a textual way. If he wants to compare or merge EMF models the needs in a logical way, he needs to do that in an Eclipse environment similar to the one he used to create these models. As such, the environment requires some plugins to be installed but it may also requires some preferences to be set, some perspective to be activated etc.. Among these plugins, there are the mandatory ones that will be use to do the compare/merge operation: EMF Compare and EGit.

EMF Compare provides additional git commands in order to compare and merge models on the command line. These commands will use an Eclipse as an headless application (no Graphical User Interface) including EMF Compare and Egit to compare models in a logical way. To provisioned such Eclipse environment, the new git commands will call a program using Oomph.

Oomph Oomph is a technology that provisions a set of plugins in an Eclipse IDE, clones Git repositories, binds Git repositories to this IDE, checks projects, sets workspace preferences... The configuration is model driven, with files called Oomph setup model files.

## Add new Git commands in your system

The basics git commands don't allow to compare or merge EMF models in a logical way. Additional git commands must be added to your system. Each git command is a shell script describing its behaviour. So, to add a new git command, a new script has to be developed. The new scripts corresponding to the git commands are:

- git logicalmerge: the "models compatible" version of the git merge command
- git logicaldiff: the "models compatible" version of the git diff command
- git logicalmergetool: the "models compatible" version of the git mergtool command

These scripts must be added on each computer that need to do "models compatible" git operations from command line interface, to enable them.

You can find the scripts at the following address: EMF Compare Git Scripts.

Note that the location of these scripts must be on your PATH environment variable. Also, they must have execution permission.

These scripts will execute a program named emfcompare-git-pgm. You also have to retrieve this program on your system. Once retrieved, you will have to export a variable named EMF_COMPARE_GIT_PGM_PATH with the path of folder containing the program emfcompare-git-pgm as value.

You can find the program at the following address: EMF Compare Git PGM. Download the one corresponding to your system.

## Create a setup file

### Installation

The setup file will allow you to configure the headless application used by your command. To create a setup file you need an Eclipse environment with the Setup Model for EMF Compare's Git commands Wizard plugin installed. Add the following p2 repository (update-site) in your update manager (in Eclipse, Help Menu > Install New Software..., Add... button on the top right corner): EMF Compare's Git commands Wizard plugin update-site

Then, select the EMF Compare Git PGM Wizards > EMF Compare Git PGM Oomph Wizard Feature and click on Finish.

This tool requires Oomph 1.0.0 or later. You may need to add the Oomph update site to the list of the available update sites to be able install and/or update Oomph: http://download.eclipse.org/oomph/updates

### Basic usage

To create a new setup model for EMF Compare's git commands, select File > New > Other ... > Oomph > Setup Model for EMF Compare's Git commands. Then click Next >.

The first page of the wizard asks you to select the project that will contain the setup model, and name that setup model. Then click Next >.

The last page of the wizard asks you to set:

- The model's root object name.
- The workspace location (absolute or relative to the setup file). If you select the Default checkbox, a workspace will be created in the temporary folder of your system.
- The installation location (absolute or relative to the setup file). If you select the Default checkbox, the Eclipse environment will be created in the temporary folder of your system.
- The projects to import in the workspace. You have to import in the workspace all project holding interconnected models in the git command you want to execute. The Import All Projects found In Current Repository checkbox is selected by default. If you unchecked it, you will have to specify in the setup model which projects you want to import.

Once all parameters have been set, click Finish.

Once created, you will able to modify the setup model. You can also create a setup model file from scratch if you prefer. This setup model can contains:

- The path (absolute or relative to the setup file) where the workspace will be created. It corresponds to a Variable task in the setup model editor. To create a Variable task, right-click on the Project element (the root element) and then select New Child > Variable. In the Properties View, you have to fill the Name field with the value "workspace.location" and the Value field with the path. If you don't provide such Variable task in your setup model, a workspace will be created in the temporary folder of your system.

- The path (absolute or relative to the setup file) where the Eclipse environment will be provisioned. To create an Variable task, right-click on the Project element (the root element) and then select New Child > Variable. In the Properties View, you have to fill the Name field with the value "installation.location" and the Value field with the path. If you don't provide such Variable task in your setup model, the Eclipse environment will be created in the temporary folder of your system.

- The paths (absolute or relative to the setup file) of the projects involved in the git command to execute. These projects will be imported in the workspace. First, you have to create a Projects Import task. Right-click on the root element and then select New Child > Projects Import. Then, right-click on the newly created Projects Import task and then select New Child > Source Locator. In the Properties View, you have to fill the Root Folder field with the path of the project to import. If you don't give any projects, then all projects found in the git repository will be imported in the workspace. In the example below, two projects will be imported: /your/project/location and /another/project/location. Note that the Locate Nested Projects allows to import every projects found under the given location."

- The additional plugins to install in the provisioned Eclipse environment. By default, only EMF Compare and EGit are provisioned in the Eclipse environment because it is the minimum and mandatory set of plugins required to execute the git command. But, you may have to add additionnal set of plugins/features. For example, you might need GMF for merging diagrams, UML2 or any specific metamodel implementation, Papyrus, etc... To do that, you have to create a P2 Director task. Right-click on the root element and then select New Child > P2 Director. Then, right-click on the newly created P2 Director task and then select New Child > Repository to add a new repository or New Child > Requirement to add a new plugin/feature. In the example below, the repository http://download.eclipse.org/releases/luna/201406250900 allows to add org.eclipse.uml2.feature.group and org.eclipse.papyrus.sdk.feature.feature.group (UML2 and Papyrus). The repository http://download.eclipse.org/modeling/emf/compare/updates/nightly/latest/ has been added. It allows to add the org.eclipse.emf.compare.uml2.feature.group and org.eclipse.emf.compare.diagram.papyrus.feature.group features (EMF compare's extensions to handle UML2 models and Papyrus Diagrams).

Please visit Oomph website for more details about Oomph.

You can find an example of setup model file for EMF compare's Git commands here: Setup Example This example contains a workspace location to edit, an installation location to edit, and additional plugins to take into account for the git command to execute. These additional plugins are Papyrus, UML2, GMF, and EMF Compare extensions.

## Git diff command with models : git logicaldiff

The logicaldiff command is the "models compatible" version of the git diff command. To see a full description of the git diff command, please visit http://git-scm.com/docs/git-diff.

The command is specified as below:

git logicaldiff [--git-dir <path>] <setup> <commit> [ <commit>] [-- <path>]

To see the changes between a revision and the HEAD revision, you should omit the second commit.

git logicaldiff [--git-dir <path>] <setup> <commit> [--] [ <path>...]

In all cases, <commit> can refers to a branch name or a commit id. In all cases, [-- <path>] option allows to filter the diff command only on files that match the <path>. In all cases, [--git-dir <path>] option allows to specify a git repository (if the command is not run inside a repository)

### Others options available

[--show-stack-trace]

Use this option to display java stack trace in console on error.

[--help (or -h)]

Dispays help for this command.

## Git merge command with models : git logicalmerge

The logicalmerge command is the "models compatible" version of the git merge command. To see a full description of the git merge command, please visit http://git-scm.com/docs/git-merge.

The command is specified as below:

git logicalmerge [--git-dir <path>] <setup> <commit>

Assume the following history exists and the current branch is master:

            A---B---C      topic
           /
      D---E---F---G        master

Then git logicalmerge mySetupModel.setup topic will replay the changes made on the topic branch since it diverged from master (i.e., E) until its current commit © on top of master, and record the result in a new commit along with the names of the two parent commits and a log message from the user describing the changes.

            A---B---C       topic
           /         \
      D---E---F---G---H     master

You can also replace the topic branch name by his commit id:

git logicalmerge mySetupModel.setup 87ad5ff

In all cases, <commit> can refers to a branch name or a commit id. In all cases, [--git-dir <path>] option allows to specify a git repository (if the command is not run inside a repository)

### Others options available

[-m message]

Set the commit message to be used for the merge commit (in case one is created).

[--show-stack-trace]

Use this option to display java stack trace in console on error.

[--help (or -h)]

Dispays help for this command.

## Git mergetool command with models : git logicalmergetool

The logicalmergetool command is the "models compatible" version of the git mergetool command. To see a full description of the git mergetool command, please visit http://git-scm.com/docs/git-mergetool.

Here is the constructions allowed for the git logicalmergetool:

git logicalmergetool <setup>

Run logical merge conflict resolution tools to resolve logical merge conflicts. In our case, it will launch an Eclipse platform with all the tools needed to resolve the conflict(s) induced by the merge. To do so, in the Eclipse environment, select the conflicting file(s) and open the contextual menu Team > Merge Tool. Once the conflict has been resolved, add the file to the index (staged area). And then commit.

## Git cherry-pick with models : git logicalcherry-pick

The logicalcherry-pick command is the logical version of the git cherry pick command. To see a full description of the git cherry-pick command, please visit http://git-scm.com/docs/git-cherry-pick.

The command is specified as below:

git logicalcherry-pick <setup> <commit>...

Assume the following history exists and the current branch is master:``

    				  A---B---C topic
    				 /

    		   D---E---F---G master,HEAD

Then `git logicalcherry-pick mySetupModel.setup A B C` will pick A,B and C commits on top of the current HEAD (in the order defined by the command).``

    				  A---B---C topic
    				 /
    		   D---E---F---G---A---B---C master,HEAD

In all cases, <commit> can refers to a branch name or a commit id.

### Conflicts

#### Resolve a conflict

If cherry-picking a commit introduces a conflict, you will have to choose how to handle it. The first option is to resolve it by using:

git logicalmergetool <setup>

It opens an Eclipse platform in which you will be able to merge the differences using the merge tool (see Git mergetool command with models : git logicalmergetool). Once you have resolved all the conflicts, add the related file to the index and close your platform. To do so you can:

- Use the contextual menu "Team > Add to Index"

- Drag and drop the files from the "Unstaged changes" area to the "Staged changes" area in the "Git Staging" view .

By the way, you can notice in the top right corner there is an Abort, Skip Commit and Continue button. This simply means that there is a interactive rebase in progress. Indeed, in EGit, cherry-picking commits is equivalent to doing an interactive rebase with only pick actions. From now on, you can either choose to continue with in UI mode (that is to say using those buttons) or go back to command line tool by closing the Eclipse platform. This documentation only describes the mechanism of the command line tool.

#### Continue

Once you have resolved all the conflicts, please hit:

git logicalcherry-pick <setup> --continue

This command will continue an in going cherry-pick. Be careful you have to resolve all conflicts before using this command otherwise you might get the following message: ``

    			fatal: Some files are in conflict:
    				project/file.ecore
    				project/file2.ecore
    			hint: You must edit all merge conflicts and then
    			hint: mark them as resolved using git add.

There is a major diffference with the merge workflow. While cherry-picking you should not commit by yourself the files but only add them to the index. If you do, you might receive the following message when you use the --continue option. ``

    No changes detected

    If there is nothing left to stage, chances are that something
    else already introduced the same changes; you might want to skip
    this patch using git logicalcherry-pick --quit

You can simply use the --quit option to continue your cherry-pick operation (see Quit option).

### Abort

A second solution while encountering a conflict is to abort the whole cherry-pick operation. To do so please hit:

git logicalcherry-pick <setup> --abort

It reverts all the commits already cherry-picked to retrieve the state before the cherry-pick command.

### Quit

The last solution you have while facing a conflict would be to "skip" the current commit and go on with the remaining commits. To do so please hit:

git logicalcherry-pick <setup> ''--quit'

The --quit option is quite different than the --quit option of the cherry-pick command in CGit. Instead of quitting an in going cherry-pick, it skips the current commit. Indeed, as mentionned above, in EGit a cherry-pick is replaced by a interactive rebase. This is why the --quit option is more like the --skip option of an interactive rebase.

### Others options available

[--git-dir <path>]

To specify the .git folder of a repository. This can be use to execute a command outside a git repository.

[--show-stack-trace]

Use this option to display java stack trace in console on error.

[--help (or -h)]

Dispay help for this command.

[--debug (or -d)]

Give the opportinity to connect a remote debugger to the logical cherry-pick application (using port 8123).

## Git rebase with models : git logicalrebase

The logicalrebase command is the logical version of the git rebase command. To see a full description of the git rebase command, please visit http://git-scm.com/docs/git-rebase.

The command is specified as below:

git logicalrebase [<upstream>] [<branch>]

[<upstream>]

Optional parameter used to reference the target commit on top of which the branch [<branch>] will be rebased. It can either be the name of a branch, the id of a commit or the name of tag. If only one parameter is given, the software will consider it to be the upstream parameter and set [<branch>] to HEAD.

Assume the following history exists and the current branch is topic:``

    				       A---B---C topic, HEAD
    				      /

    		   D---E---F---G master

Then `git rebase mySetupModel.setup master` will rebase the branch topic on top of master.``

    		   D---E---F---G---A---B---C master, topic, HEAD

[<branch>]

Optional parameter used to reference what is going to be rebased. It can either be the name of a branch, the id of a commit or the name of tag.

For example, assume the following history exists and the current branch is master:``

    				       A---B---C topic
    				      /

    		   D---E---F---G master, HEAD

Then `git rebase mySetupModel.setup master topic` will checkout the branch topic and the rebase it on top of master.``

    		   D---E---F---G---A---B---C master, topic, HEAD

Hint to remember the parameter order:

- `git rebase mySetupModel.setup master` = Rebase on master the HEAD
- `git rebase mySetupModel.setup master topic` = Rebase on master the branch topic
- `git rebase mySetupModel.setup master topic` equivalent to `git rebase mySetupModel.setup master` if HEAD is on same commit than topic.

If you do not specify any branch, `git rebase mySetupModel.setup` will try to rebase the current branch on top of its remote tracking branch (see branch.<name>.remote and branch.<name>.merge options in git-config).

For example, assume the following history exists. The current branch is master which tracks the remote branch origin/master:``

    		          A---B---C origin/master
            /
       D---E---F---G master, HEAD

Then `git rebase mySetupModel.setup` will rebase master on top of origin/master.``

    		   D---E---A---B---C---F---G master, origin/master, HEAD

### Conflicts

#### Resolve a conflict

If rebasing a commit introduces a conflict, you will have to choose how to handle it. The first option is to resolve it by using:

git logicalmergetool <setup>

It opens an Eclipse platform in which you will be able to merge the differences using the merge tool (see Git mergetool command with models : git logicalmergetool). Once you have resolved all the conflicts, add the related file to the index and close your platform. To do so you can:

- Use the contextual menu "Team > Add to Index"

- Drag and drop the files from the "Unstaged changes" area to the "Staged changes" area in the "Git Staging" view .

By the way, you can notice in the top right corner there is an Abort, Skip Commit and Continue button. This simply means that there is a interactive rebase in progress. Indeed, in EGit, even a normal rebase operation is equivalent to doing an interactive rebase with only pick actions. From now on, you can either choose to continue with in UI mode (that is to say using those buttons) or go back to command line tool by closing the Eclipse platform. This documentation only describes the mechanism of the command line tool.

#### Continue

Once you have resolved all the conflicts, please hit:

git logicalrebase <setup> --continue

This command will continue an in going rebase. Be careful you have to resolve all conflicts before using this command otherwise you might get the following message: ``

    			fatal: Some files are in conflict:
    				project/file.ecore
    				project/file2.ecore
    			hint: You must edit all merge conflicts and then
    			hint: mark them as resolved using git add.

There is a major diffference with the merge workflow. While rebasing you should not commit by yourself the files but only add them to the index. If you do, you might receive the following message when you use the --continue option. ``

    No changes - did you forget to use 'git add'?

    If there is nothing left to stage, chances are that something else
    already introduced the same changes; you might want to skip this patch.

    When you have resolved this problem, run "git logicalrebase --continue".
    If you prefer to skip this patch, run "git logicalrebase --skip" instead.
    To check out the original branch and stop rebasing, run "git logicalrebase --abort".

You can simply use the --skip option to continue your rebase operation (see Skip option).

### Abort

A second solution while encountering a conflict is to abort the whole rebase operation. To do so please hit:

git rebase <setup> --abort

### Skip

The last solution you have while facing a conflict, would be to "skip" the current commit and go on with the remaining commits to rebase. To do so please hit:

git rebase <setup> --quit

### Others options available

[--git-dir <path>]

To specify the .git folder of a repository. This can be use to execute a command outside a git repository.

[--show-stack-trace]

Use this option to display java stack trace in console on error.

[--help (or -h)]

Dispay help for this command.

## Git pull with models : git logicalpull

The logicalpull command is the logical version of the git pull command. To see a full description of the git pull command, please visit http://git-scm.com/docs/git-pull.

The command is specified as below:

git logicalpull <setup>

Assume the following history exists and the current branch is master:

            A---B---C      master on origin
           /
      D---E---F---G        master
          ^
          origin/master in your repository

Basically a git logicalpull is a git fetch followed by a git logicalmerge of the fetched branch. So git logicalpull mySetupModel.setup will fetch and replay the changes from the remote master branch since it diverged from the local master (i.e., E) until its current commit ( C) on top of master, and record the result in a new commit along with the names of the two parent commits and a log message from the user describing the changes.

            A---B---C       origin/master
           /         \
      D---E---F---G---H     master

If the command introduces conflicts, you will have to launch the git logicalmergetool to resolve them.

### Others options available

[--show-stack-trace]

Use this option to display java stack trace in console on error.

[--help (or -h)]

Dispays help for this command.

## Known bugs & limitations

### First use

The first time the product is launched a stack trace is displayed in the console(see below). This error does not prevent the product to be used however it may be misleading for users. After the first launch this error disappears.

    org.osgi.framework.BundleException: Could not resolve module: org.eclipse.equinox.ds [2]
      Unresolved requirement: Import-Package: org.eclipse.equinox.internal.util.event; version="1.0.0"

    	at org.eclipse.osgi.container.Module.start(Module.java:434)
    	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1582)
    	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1562)
    	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1533)
    	at org.eclipse.osgi.container.SystemModule.startWorker(SystemModule.java:242)
    	at org.eclipse.osgi.container.Module.doStart(Module.java:571)
    	at org.eclipse.osgi.container.Module.start(Module.java:439)
    	at org.eclipse.osgi.container.SystemModule.start(SystemModule.java:172)
    	at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:393)
    	at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:412)
    	at org.eclipse.osgi.launch.Equinox.start(Equinox.java:115)
    	at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:318)
    	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:231)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:483)
    	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:648)
    	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:603)
    	at org.eclipse.equinox.launcher.Main.run(Main.java:1465)
    	at org.eclipse.equinox.launcher.Main.main(Main.java:1438)

A bug has been reported concerning this error: https://bugs.eclipse.org/bugs/show_bug.cgi?id=453432

### Merge tool

The merge tool doesn't work correctly on logical models. the problem is known and a patch has been made to fix it. Since the problem concerns EGit & EMF Compare, we need to stay EGit team to integrate the following contribution:

- https://git.eclipse.org/r/#/c/36026/

Once integrated, the following EMF Compare contributions will be integrated too:

- https://git.eclipse.org/r/#/c/35541/
- https://git.eclipse.org/r/#/c/36025/

Then, the merge tool will work correctly.

### Cherry-pick empty commit

If you try to cherry-pick a commit that introduces changes that already belong to the worktree, the operation may stop on a dirty state. For example, if you have cherry-picked a commit that belongs to the ancestor tree of HEAD. The characteristics of this dirty state are:

1. Wrong position of HEAD.
2. Some modified files in the working tree (use git status command).

This problem comes from a EGit/JGit problem (see bug 451159). A workaround would be to find the previous position of HEAD using the git reflog command. Then, use the git reset --hard {$CommitId}. This will reset HEAD to its previous position ( Use with caution).