Plastic SCM - GitSync guide


Intro

As you likely know by now, Plastic SCM is a full featured DVCS (Distributed Version Control Software). And, Plastic SCM also speaks the Git network protocol.

Plastic SCM is able to push and pull changes directly to any remote Git server. This is because Plastic supports the https:// and git:// protocols for both pushing and pulling changesets.

This feature immediately turns Plastic SCM into a DVCS fully compatible with Git. The advantages of this means that you can use Plastic or Git on your workstation, and still participate on Git projects (GitHub, CodePlex and many more).

Plastic - push/pull - Git


What is GitSync?

This can be a first approach: GitSync is a native Windows DVCS connected to GitHub. So, it virtually turns Plastic SCM into a full-fledged Windows client for Git.

Note: GitSync is not technically a new Git client: You would be using Plastic SCM on the client side but being able to push/pull to Git servers (using https or Git protocols).

Imagine that you're a developer using GitHub (or Bitbucket, or maybe CodePlex). In any case, there are things you like: using a cloud-based repository for your code, and Windows to develop. And things you don't like: being forced to use the CLI, and lack of really awesome GUI tools.

So, you wish you had everything: Cloud repositories, the DVCS power, and awesome tools for Windows.

That's what you get with GitSync.


Feature list

The capabilities of GitSync are:

  • Direct push/pull - Including all commits, comments, branches, merge tracking and tags.
  • Adding/deleting or moving files - No limits at any of the two sides.
  • Full merge tracking - You can merge at Git side and Plastic will recognize the merge tracking. And, the same is true in the Plastic-to-Git direction. That's the benefit of Plastic SCM and Git being full DVCS!
  • Conflict management - It is possible to make changes on the same branch on the Git and Plastic sides concurrently and Plastic will handle the data exchange, pull the changes, request the user to run a merge, then push the solved conflict (as you'd do if you just were using a full Git setup).

How it works?

Since an image is worth a thousand words, let's go, step by step, through an entire push and pull process.


Initial scenario

You've a Git repo and then you pull it on Plastic. As a result, you get an exact clone with the branches and commits you had in Git now converted to Plastic, and what's best about this, is the ability to be rendered in the Branch Explorer:

How GitSync works - Initial scenario


Creating new commit on the Git side

The next image shows what happens when a new commit is created on the Git side, and how the pull from Plastic SCM retrieves it.

Instead of just performing a simple change, the figure shows a merge from big_feature branch into master. The result in Plastic SCM mimics what happened at the Git side, adding the merge link (which is rendered as a green line) on the Plastic Branch Explorer:

How GitSync works - Creating new commit on the Git side


Creating new changeset on the Plastic side

The next step is performing a change in Plastic SCM and pushing the change to Git. To create a more complete example, instead of just creating a new changeset, we will also perform a merge.

The changesets 6 and 7 are created on the Plastic side, then they're pushed to Git. As you can see in the figure below, the merge information (multiple parents on the Git repo) is also sent from Plastic to Git.

How GitSync works - Creating new commit on the Plastic side

So far, the changes were done at one side or the other, but not at the two sides concurrently.


Performing changes concurrently: conflicts

The following picture shows what happens when developers work on the same branch at the same time. One new commit is created in Git (on green) and a new one in Plastic (orange):

How GitSync works - Performing changes concurrently: conflicts

If the Plastic developer tries to push to Git, an error will show up since there are conflicting changes (the same that would happen on a similar scenario on a pure Plastic or pure Git setup). The steps to follow are:

  1. First pull the changes from Git
  2. A new "subbranch" will be created placing the 88ffa changeset correctly.

    How GitSync works - Performing changes concurrently: conflicts

  3. The next steps will be resolving the merge conflict at the Plastic SCM side, and then completing the push:

    How GitSync works - Performing changes concurrently: conflicts

At the end of the interaction, both repositories will look the same, and will let developers work together at both sides.

Note: Since Plastic SCM is a full DVCS (like Git) it can clone a Git repository and later push changes to it... entirely! We do not restrict to a single branch. You can create branches on Plastic and push them to Git. You can create branches on Git and pull them to Plastic.

The gitsync.conf file

The GitSync configuration file (gitsync.conf) lets you include information that will be automatically used during the GitSync operations.

This information is related to the mapping between two Plastic SCM and Git objects:

  • User accounts
  • Xlinks/Submodules information
The gitsync.conf file must be located in the Plastic SCM client folder or on the user local directory (within Documents and Settings or Users in Windows systems, or home in UNIX based systems).

Mapping user accounts

In the gitsync.conf file, we can define a mapping between Plastic and Git (emails). This information will be used as author and committer when committing to Git.

This info is added on the email-mapping section with the following format:

plastic_user = git_email_address

This is an example of gitsync.conf file:

[email-mapping]
asalim = asalim@mymailprovider.com
ubuntu = ubuntu@linuxprovider.com

Mapping Plastic SCM Xlinks and Git submodules

A Git submodule is just a pointer to a commit in a different repository. It doesn't propagate operations between submodules or handle the branching between the repositories, so this very basic information is enough for the submodules work.

A Plastic Xlink object is more complex than the Git submodule: the Xlinks allow the user to set relative servers, set rules for the branch expansion, and define whether the Xlink is writable or not.

In general terms, we can say that Git submodules and Plastic Xlinks have the same mission: pointing to a commit in a different repository. So a direct mapping can be established between:

  • A Git commit ↔ A Plastic changeset
  • A Git repository url ↔ A Plastic repository specification

GitSync lets the user create Plastic Xlinks from Git submodules and vice versa. The Git submodules and the Plastic Xlinks can be synchronized using GitSync:

  • The Git submodules are converted into Plastic Xlinks during the pull operation.
  • The Plastic Xlinks are converted into Git submodules during the push operation.

Please note that before synchronizing a repository with Xlinks/Submodules, the target repositories must be synchronized.

To synchronize a repository with Xlinks/Submodules, the mapping information must be added on the gitsync.conf file. This info is added on the submodules section with the following format:

git_repository_url -> plastic_repository_spec [writable:true|false] [relativeserver:true|false]
  • If the Git submodule has to be converted on a writable Plastic Xlink, then the writable field must be included as writable:true. If the writable field is omitted or it's set to false, the Xlink is created as readonly.
  • If the Git submodule must be converted on a Plastic Xlink with a relative server, the field relativeserver must be included as relativeserver:true. If the relativeserver field is omitted or it is set to false, then the Xlink is created against the Plastic repository server (as non-relative Xlink).

This would be a valid configuration example:

[submodules]
git://localhost/code -> code@localhost:8084 writable:true relativeserver:true
git://localhost/doc -> doc@localhost:8084 writable:false relativeserver:true

GitSync restrictions

There are two Git operations that are restricted when using GitSync:

  • rebase command
  • merge (fast-forward) command

These Git commands don't take into account the history of your changes. Although the user can work in a parallel way, Git talks about history like something linear. But Plastic prioritizes keeping the changes history.

Plastic SCM takes into account the whole history of the changes you make. This means that Plastic doesn't rewrite history. It is not that we're against it, it was a design decision, a philosophy.

The changes history is reflected when working on branches and merging. Because Plastic SCM is able to solve and show how the history is, we recommend you to avoid using those Git commands when working with GitSync.

  • Rebasing is a subtle topic in Git - You can only do it before you push (in fact, many recommend that you never use it) and most of the time it is used to be able to understand the history without going crazy with all the merging:

    GitSync restrictions - Git rebase

    We don't handle rebases in Git fashion.
  • The Git fast-forward merge command does something similar, solving the merge in a linear way:

    GitSync restrictions - Git fast-forward merge

    Use the merge --no-ff command to keep the history.

Plastic has the Branch Explorer which simply lets you understand what is going on, graphically. This way you are not distracted and you don't miss rebasing.

When you diff a branch with several merges, it is hard to see what you really changed on the branch and what comes from the merge... this is also solved in Plastic:

GitSync - Plastic merge

We recommend that you not to use the Git rebase and merge (fast-forward) command to avoid unexpected results when synchronizing your Plastic-Git repositories.

Direct push/pull

As we've seen previously, Plastic can push and pull directly to remote Git servers using both native Git and https protocols, which includes well-known sites such as GitHub, BitKeeper, CodePlex and many others.

When we started developing the Git-bidirectional synchronization with Plastic SCM, we had the following scenarios in mind:

  • Developers already using Plastic SCM who want to contribute to projects in sites like GitHub, CodePlex, BitKeeper and others.
  • Developers working on teams using Git as primary server who prefer to use Plastic SCM but need to contribute changes back to the main server.
  • Teams gradually adopting Plastic SCM who need to contribute to other teams on Git.

We went the hard way for a solution: we didn't come up with some sort of intermediate script to convert changes from one system to the other, or doing fast-import/export, imposing a ton of limitations. But we actually implemented was the Git network protocols in Plastic as a layer able to directly pull and push to Git.

Plastic starts a negotiation phase with the remote Git server, as a Git command would do, speaking the Git protocol. It is a core feature, not an add-on script.

As we've said, GitSync implements the smart-protocol and:

  • It can negotiate with a remote Git receive-pack to upload data (negotiating which changesets/commits are needed and generating the correct pack file from Plastic repository data to be sent to Git).
  • It can also negotiate with a remote upload-pack to decide which commits need to be packaged, download the pack and import it into Plastic.

The first pull

Let's start by connecting to a GitHub repository.

  1. If you go to GitHub and browse the repos, you'll probably find something like a list of "trendy" repos. In the example figure, I've selected one of them which turned out to be the corefx repository:

    GitSync - First pull - Select GitHub repo

    Now, to pull it to Plastic I've created a repo to "host it" (called corefx too) and went to the initially empty Branch Explorer, then to the context menu option to launch the Sync with Git:

    GitSync - First pull - Sync with Git

  2. Then you launch the Sync dialog (which is very similar to the replication dialog to push/pull changes between Plastic servers) and enter the URL of the Git repo:

    GitSync - First pull - Sync dialog

    No need for credentials now since we're just pulling (cloning) from a public repo. You'll need to specify them in case you need to push and then the server requires you to be an authenticated user.

  3. Just press Sync and the process (pull) will start up as follows:

    GitSync - First pull - Sync

    Note: This operation can be done by using the command line in the following way: cm sync corefx git https://github.com/corefx/corefx.git

    Assuming the local corefx repo is empty, it will calculate the changesets and branches it needs to pull from the remote GitHub repo, and will pull them:

    GitSync - First pull - Sync command line

    In order to pull new changes done at the GitHub side, you'll simply re-run the same command:

    cm sync corefx git https://github.com/corefx/corefx.git

    And it will now calculate and pull only the new changes made at the Git side, if any.

    You're currently pulling Git changesets and branches directly to your local Plastic SCM repository:

    GitSync - First pull - Pulling

    GitSync - First pull - Pulling summary

  4. Once the replication is complete, we'll go back to the workspace explorer, and we'll update our workspace to download the source files.
  5. Refresh the Branch Explorer too. And you'll be able to render the just imported Git changesets in a typical Plastic SCM way:

    GitSync - First pull - Branch Explorer

    And now, right-clicking any changeset (commit in Git jargon), you'll be able to check differences with our built-in diff system:

    GitSync - First pull - Diff

Now you're ready to do more changes in Plastic whether branches, merges, anything. Then repeat the same process to sync to Git (which will in turn push or pull changes and even ask you to solve merges before pushing back to Git, if concurrent changes were done on the same branches).


Pushing to Git

We're going to push one of our Plastic repositories to GitHub. You'll see that this process is similar to the previous one.

Ok! Let's start!

  1. I created a new GitHub repository in order to export my Plastic repository to GitHub:

    GitSync - First push - Create GitHub repo

  2. I've chose my dokancode Plastic repo. In the Branch Explorer view, right-click one of its branches and, as we did in the previous chapter, select the Sync with Git menu option:

    GitSync - First push - Sync with Git

    The Sync dialog will be launched.

  3. Then, enter the GitHub repository URL and the credentials if needed:

    GitSync - First push - Sync dialog

  4. Then, click the Sync button to start the synchronization. In this case, we're going to push (or export) our Plastic repository:

    GitSync - First push - Sync

    We're currently pushing Plastic SCM changesets and branches directly to my GitHub repository.

    Note: This operation can be done by using the command line in the following way: cm sync dokancode git https://github.com/mbctesting/dokancode.git

    Assuming the GitHub dokancode repo is empty, GitSync will calculate the changesets and branches it needs to push from the Plastic repo, and will push them:

    GitSync - First push - Sync command line

    Once the push operation is finished, we can see a summary with the objects that have been exporting:

    GitSync - First push - Pushing

    GitSync - First push - Pushing summary

  5. If we go back to GitHub and refresh the dokancode repository, we'll see the exported objects from Plastic:

    GitSync - First push - GitHub

Now we're ready to work with the repository in both sides: Plastic SCM and GitHub. We'll be able to create branches, do changes... and synchronize again by pulling/pushing.


Working on the both sides

In this chapter we're going to show you how to work with the dokancode repo, both in the GitHub and Plastic sides, applying some basic operations.

This is the recommended step - Before performing any changes at either of the sides, you must synchronize your repo (using the Sync with Git action) to avoid conflicts.

Changes at the Git side

Now I'm going to run some operations on the master branch:

  1. Delete the license.txt file:

    GitSync - Git side - Delete a file

  2. Edit the dokan-net-0.6.0\readme_dokan.txt file:

    GitSync - Git side - Edit a file

  3. And move it to dokan-net-0.6.0\DokanNet folder:

    GitSync - Git side - Move a file

  4. And then, I'm going to create a new branch (scm007).

    GitSync - Git side - Create new branch

  5. Add two new files:

    GitSync - Git side - Add new file

    GitSync - Git side - Add new file

  6. And edit one of those files:

    GitSync - Git side - Edit new file

The commits are done and now we're ready to see them in the Plastic side.

As we've learned during this guide, we've seen that GitSync is capable of calculating what's new at the other side, negotiate with the remote server and push the changes.

  1. So let's go to synchronize the Plastic repo with the GitHub one by running a Sync with Git action:

    GitSync - Git side - Sync with Git

    GitSync - Git side - Synchronize

  2. By clicking Sync, the synchronization will begin and will pull to the Plastic repo the changes we performed on the GitHub side:

    GitSync - Git side - Sync

    Once the synchronization finished:

    GitSync - Git side - Sync finished

  3. We can see a summary with the imported objects:

    GitSync - Git side - Sync summary

  4. If we go back to the Branch Explorer and refresh the view, we'll see the changes done in the GitHub side that have been imported to Plastic:

    GitSync - Git side - Branch Explorer

  5. We can open the Changesets view to see these GitHub changes:

    GitSync - Git side - Changesets view

  6. And, if we want to go deeper, we can confirm the changes done with the readme_dokan.txt file in the GitHub side. We can see the history of that file to check that those changes have been applied with the synchronization:

    GitSync - Git side - Changes

Now we can continue performing changes at the Plastic side.


Changes at the Plastic side

I'm going to perform some changes on the scm005 branch. At this point, both the Git and Plastic sides have the same content. We can check it on both sides:

GitSync - Plastic side

GitSync - Git side

In this branch I'm going to:

  1. Add a new file:

    GitSync - Plastic side - Add new file

  2. Edit the DokanOperation.cs file:

    GitSync - Plastic side - Edit file

    These are the new changes:

    GitSync - Plastic side - New changes

  3. Once the changes are done, I'm going to synchronize the GitHub repository by running a Sync with Git operation:

    GitSync - Plastic side - Sync with Git

  4. Once the synchronization is done, we can see the summary:

    GitSync - Plastic side - Sync summary

    The summary tells us that the synchronization has sent two changesets involved in one branch:

    GitSync - Plastic side - Changesets

  5. If we go to the GitHub side, we can see these new changes that were done in the Plastic side:

    GitSync - Plastic side - GitHub


Plastic and Git branches conversion

If you noticed, the Plastic main branch is mapped to Git master branch. This mapping is also considered for the children branches of main on Plastic. This means that the Plastic branches are converted into Git branches by removing the hierarchy and replacing the / with -. And this rule is also valid when a Git branch is converted into a Plastic branch: the - character is used to recreate the hierarchy in Plastic.

In the examples before, the Plastic branch /main/scm005 is converted to master-scm005. And the Git branch scm007 under master, is converted to /main/scm007:

GitSync - Plastic and Git hierarchy

The - character is also allowed as part of the branch name like the following examples:

Branch - Git side Branch - Plastic side
master /main
master-fix-5.0 /main/fix-5.0
master-fix-5.0-task1 /main/fix-5.0/task1

Full merge tracking

Since Plastic SCM handles the same concepts as Git (DAG, commits, merge links, and so on), it is rather easy to share the merge tracking. You do a merge in Git, fine, you can get it back to Plastic. If you do a merge in Plastic, fine, you can push even the merge link back to Git.

The most difficult feature for us to handle is related to the "precise item tracking"; we do (and Git doesn't). Plastic has an internal id associated to each file and directory. It means we can easily handle tons of merge conflicts that are hard to track for Git (like a divergent move, something trivial for Plastic).

In the following examples we'll see how the merge tracking works when using GitSync.


Merge on the Plastic side

We're going to create two branches:

  1. Branch scm008 - I'll edit the DokanResetTimeout method in the DokanNet.cs file, move it inside the file, and add a new field:

    GitSync - Plastic side - Merge - Edit file

  2. Branch scm009 - I'll move the DokanNet.cs file to another folder, then I'll move the method DokanResetTimeout to another class and edit it:

    GitSync - Plastic side - Merge - Move file

  3. Once the changes are done on different branches, I'm going to merge them to the main branch, and I get this result:

    GitSync - Plastic side - Merge

    GitSync - Plastic side - Merge result

  4. Now I'm going to synchronize my repositories on both sides, as you know, using the Sync with Git operation. This way, I will push these merges on the Git side.

The new branches have been pushed and the merge tracking looks like this on the Git side:

GitSync - Plastic side - Pushed to Git


Merge on the Git side

Now we're going to see a merge in the Git side is tracked on the Plastic one.

  1. I'm going to create a new branch and I'll create a new file and edited another one:

    GitSync - Git side - Merge - Changes

    GitSync - Git side - Merge - Changes

  2. Once the commits are done, I'm going to perform a merge from the scm010 branch to the master one:

    GitSync - Git side - Merge

    Note that the merge is done using the --no-ff option as we've seen in the GitSync restrictions section.

    GitSync - Git side - Merge done

    The merge is done and now we're going to pull these changes to the remote Git repo:

    GitSync - Git side - Merge - Changes

  3. Once the local Git changes have been pulled to the remote Git repo, let's go to synchronize our repos. This means that the latest changes will be pulled to the Plastic repo. If we run a Sync with Git operation:

    GitSync - Git side - Merge - Sync with Git

  4. ...and refresh the Branch Explorer once the synchronization is finished, we'll see how the changes and merge done in the Git side have been pulled into the Plastic one:

    GitSync - Git side - Merge - Branch Explorer


Conflict management

As we've seen in the How it works chapter, we can make changes concurrently both in the Plastic and Git side. This means that you can work on the same branch on the two systems and reconcile changes (as you do when you use a pure Plastic environment or a pure Git one).

We're going to see how you can manage that situation with GitSync and Plastic.

Let's start by using one of the previous examples. In the Changes at the Git side section we made some changes at the GitHub side. This is the what I did:

  1. In the master branch - I deleted the license.txt file, edited the dokan-net-0.6.0\readme_dokan.txt file, and moved it to the dokan-net-0.6.0\DokanNet folder.
  2. Then I created a new branch (scm007) where - I added two new files (ArrayIndex.cs and ArrayInitialization.cs) and edited one of them (ArrayIndex.cs).

And now, I'm going to perform some changes in the Plastic side:

  1. In the main branch, I'm going to edit the DokanNet.cs file:

    GitSync - Conflict management - Plastic side - Edit file

  2. And add 3 new files:

    GitSync - Conflict management - Plastic side - Add files

Once the changes are done, I decided to synchronize both repos using the Sync with Git operation:

GitSync - Conflict management - Sync with Git

GitSync - Conflict management - Sync with Git

When the synchronization is finished, a message will tell us that a merge is needed!

GitSync - Conflict management - Merge needed

And this is because we made some changes in the same branch on both the Git and Plastic sides.

In the summary, will see that the main (or master) branch is the one that requires a merge operation:

GitSync - Conflict management - Merge needed - Summary

And it's true: We applied some changes in the master branch on the Git side, and some other changes in the main branch on the Plastic side. Remember, that main and master is the same branch but using different names (see the Git-Plastic Dictionary for further information).

As we've seen in the How it works section, we have to resolve the merge conflict at the Plastic side. So let's do it!

  1. If we update the Branch Explorer, we'll see that:
    • First, the main branch has multiple "heads" that must be merged. This is because these conflicts are handled as a subbranch in Plastic SCM.
    • Second, the scm007 branch has been synchronized (pulled from GitHub to Plastic SCM).

    GitSync - Conflict management - Merge needed - Branch Explorer

  2. To solve this conflict, we're going to run a merge from the "GitHub" head (the head of the subbranch):

    GitSync - Conflict management - Merge needed - Merge from GitHub head

    We'll see the changes that are going to be merged:

    GitSync - Conflict management - Merge needed - Changes to be merged

  3. By clicking the Process all merges button, then the items have been automatically merged.
  4. The last step (as you know) is to checkin (confirm) the changes in the Pending changes view:

    GitSync - Conflict management - Merge needed - Checkin

  5. Once you clicked the Checkin button, you'll see that the two "heads" are merged into only one head, the one from the main branch:

    GitSync - Conflict management - Merge solved

  6. The merge conflict is now solved. But we need to complete the synchronization by pushing in the Git side the changes done in the Plastic one. And, as you may already know, this is done by using the Sync with Git action.

Once this operation is finished, both repos are fully synchronized. This means that we have the same content on both sides.


Last updated

June 16, 2017
  • Read how the branches conversion between Plastic and Git, and vice versa, works. We also updated the related screenshots.
  • April 12, 2016
  • Publication date.