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:

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 >.

Setup Model for EMF Compare's Git commands wizard

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 >.

Setup Model for EMF Compare's Git commands wizard

The last page of the wizard asks you to set:

Once all parameters have been set, click Finish.

Setup Model for EMF Compare's Git commands wizard

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:

Setup Model for EMF Compare's Git commands wizard

Setup Model for EMF Compare's Git commands wizard

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:

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:

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:

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

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).