Who we are

We are the developers of Plastic SCM, a full version control stack (not a Git variant). We work on the strongest branching and merging you can find, and a core that doesn't cringe with huge binaries and repos. We also develop the GUIs, mergetools and everything needed to give you the full version control stack.

If you want to give it a try, download it from here.

We also code SemanticMerge, and the gmaster Git client.

Archive branches in Plastic SCM

Friday, June 21, 2019 Sergio L. 0 Comments

UPDATE September 26, 2019: Added information on how to distribute branch explorer filters through Plastic SCM's Global Configuration.


One common workflow in other version controls such as Git is as follows: you create your bugfix or feature branch, and once you are finished with it and your changes get integrated, you delete it. Plastic SCM, for traceability reasons, does not support deleting branches. Because branches are the central part of our development philosophy, both the core and the GUIs can handle hundreds of thousands of them without a problem. (Our main repo has almost 25K branches right now, and that's actually very few!) So, you don't have to delete them for performance reasons.

But, you can "archive" branches you no longer need to reduce the clutter, and even to adapt your workflow from your previous SCM tool if you are unfamiliar with Plastic SCM. Let me show you how!

Just the steps

If you are a seasoned Plastic SCM user, then you don't need my step-by-step guidance. This is what we are going to do:

  1. Create a new attribute to point branches that are no longer needed.
  2. Assign that attribute to already existing branches using a shell script.
  3. Setup a server-side after-mkbranch trigger to assign that attribute to new branches automatically.
  4. Add an external tool action on branches to have a shortcut on the GUIs to apply the attribute with the right value.
  5. Change the query on the branches list to include non-archived branches.
  6. Add an exclusion filter to the Branch Explorer to filter out archived branches.
  7. (Optional) Distribute the Branch Explorer filter to your colleagues through Plastic SCM's Global Config.

Continue reading for the detailed steps (and even some tips!)

Setting up attributes and branches

Every object in Plastic SCM (branches, changesets, labels, and shelves) can have attributes. Attributes are metadata that can serve any purpose. For example, we use attributes to indicate to our CI system when a branch is ready to be integrated. Likewise, we can have an attribute to indicate that a branch is no longer necessary. We will call this attribute ARCHIVED, and it will have two values: false for when the branch is still in use, and true for when we want to remove the branch from the GUIs.

To create our new attribute, execute the following command. My repository spec is CHIPEIT@localhost:8087; replace it for yours!

> cm attribute create att:ARCHIVED@CHIPEIT@localhost:8087

Alternatively, you can execute this other command from a workspace. The attribute will be created in the repository the workspace is pointing at:

> cm attribute create ARCHIVED
Protip: cm tries to infer as much information from context as possible – if you execute a command from a workspace, you don't need to specify the repository. This is valid not only for the attribute command, but for others as well, such as find or branch.

Set ARCHIVED attribute for already existing branches

Now, we need to set all our branches either as archived or not archived. Maybe you want to do so based on a date, or a branch name. How we do it in a convenient manner depends on the Operating System or shell you are using. I'll provide scripts for PowerShell and Bash to set ALL branches as NOT archived. Adapt them to suit your needs, or feel free to share a script for other shells.

Remember the previous tip! Either execute these scripts from a workspace, or fix them to have the repository specification:

## PowerShell

ForEach ($branch in $(cm find branches --format="br:{name}" --nototal))
{
    cm attribute set att:ARCHIVED $branch false; // Without repspec
    cm attribute set att:ARCHIVED@CHIPEIT@localhost:8087 false; // With repspec
}
## Bash / ZSH

for branch in $(cm find branches --format="br:{name}" --nototal));
do
    cm attribute set att:ARCHIVED $branch false
done

You can check that everything worked OK from the GUIs, or with a little bit of cm find:

> cm find "branches where attribute = 'ARCHIVED' and ATTRVALUE = 'false'"

Setting the attribute on branch creation

So far so good. Now, it is time to automate setting the attribute on branch creation. We can't expect that we will always remember to do so! We will use a trigger for that. Specifically, a server-side after-mkbranch trigger. We need to set it up from the command line. Worry not, this is what you need to do:

First, ensure that the server process has in its path a valid cm executable. Either that or specify the full cm path in the following scripts. We will also need a valid client.conf file available on the same machine as the server, and accessible by the server process. You can use your own client.conf, located in %LOCALAPPDATA%\plastic4 for Windows users, and in $HOME/.plastic4 for macOS and Linux users.

This step is important – the process executing the trigger is the Plastic SCM server one. By default, the server process runs under another user with different privileges and different PATH environment variable than your user profile. Without a valid cm executable in its PATH, and a valid client.conf file accessible by it, the trigger execution will fail.

Then, create a script in a well-known location accessible by the server with the following content:

## PowerShell

$ATT_SPEC = "att:ARCHIVED@$env:PLASTIC_REPOSITORY_NAME"
$ATT_VAL = "false"
$BR_SPEC = "br:$env:PLASTIC_FULL_BRANCH_NAME@$env:PLASITC_REPOSITORY_NAME"
cm attribute set $ATT_SPEC $BR_SPEC $ATT_VAL -clientconf=C:\path\to\valid\client.conf
## Bash / ZSH

#!/usr/bin/env sh
ATT_SPEC=att:ARCHIVED@$PLASTIC_REPOSITORY_NAME
ATT_VAL=false
BR_SPEC=br:$PLASTIC_FULL_BRANCH_NAME@$PLASTIC_REPOSITORY_NAME
cm attribute set $ATT_SPEC $BR_SPEC $ATT_VAL -clientconf=/path/to/valid/client.conf

Finally, create the trigger:

## Windows
> cm trigger create after-mkbranch "ARCHIVED->false" "PowerShell C:\full\path\to\script.ps1"

## *NIX
$ chmod 777 /path/to/script.sh
$ cm trigger create after-mkbranch "ARCHIVED->false" "/path/to/script.sh"
Protip: To debug your script, export the PLASTIC_XYZ environment variables and execute the script by hand. In *NIX OSs, impersonate the plasticscm user with the sudo command.

If you want, you can add a filter so that the trigger only executes in the repositories you need to:

> cm trigger create (...) --filter="rep:CHIPEIT"

If something went wrong creating the trigger, you can list the triggers with the list / ls subcommand and delete them with the delete / rm one. Easy!

> cm trigger list
1 ARCHIVED->false /home/pi/scripts/set-att-archived-false.sh sergio after-mkbranch rep:CHIPEIT
> cm trigger delete after-mkbranch 1

Marking branches as archived from the GUIs

You can apply attributes from all three Plastic SCM GUIs (Windows, macOS and Linux). To do so, you must go to the properties panel, and there, click on the appropriate button, search for the attribute you want, and finally give it a value.

However, there is a way to apply the attribute you need to the branch you want that feels more natural for our use case. I'm talking about using the "external tools". You can learn everything you need to know about external tools in this blogpost, but for now suffice to say that all you need to do is add the following line to your externaltools.conf configuration file:

branch | Mark this branch as 'ARCHIVED' | cm | attribute set att:ARCHIVED @object true -path="@wkpath"
The externaltools.conf file must be located at %LOCALAPPDATA%\plastic4 on Windows, and $HOME/.plastic4 on macOS and GNU/Linux. You need to restart the GUI for the changes to take effect.

Now, there is a new item in branches' context menu. To check it out, right click on a branch either in the Branch Explorer or in the branches list, and at the end, under External tools, you will see Mark this branch as "ARCHIVED". You can check that it works by clicking on it and then refreshing the attributes of the object in the properties panel.

Hiding branches from the GUI

There are two places we are going to tweak to hide archived branches. One is the branches list, and the other is the Branch Explorer.

...on the branches list

For the first one, we only need a little help from the cm find. We must search for branches that have the ARCHIVED attribute set, and that the ARCHIVED attribute value is equals to false. Something like this:

> cm find branch where attribute = 'ARCHIVED' and attrvalue = 'false'

After setting a branch as archived on this list, you need to manually refresh the view, since it doesn't reload automatically after executing an external action. (Would you want to have this as a feature?)

Protip: The cm find allows human friendly dates as constants. So, instead of having to specify a concrete date such as 1/1/2019, you can use '1 week ago', '2 years ag0', and so on.

...on the Branch Explorer

The Branch Explorer allows you to run more fine-grained queries to customize the way the branches diagram looks. Personally, I color branches based on their status on the CI system – red for failed, yellow for in testing, and green for ready. But it not only allows you to change a branches' colors, it can also hide branches from the diagram. That's what we are going to do.

On the right panel of the Branch Explorer, look for Filters and conditional format. There, click on Add exclusion, and, in the box that will appear, type the following:

attribute = 'ARCHIVED' and attrvalue = 'true'

Remember to give it a title too! Mine was Hide archived branches as you can see in the screenshot above.

Because now we want to exclude branches that match the query (and not the other way around, like on the branches list), we must change the condition here. Once the exclusion filter is in place, click on Save, and then on Apply. The Branch Explorer should refresh automatically, and all the branches that are archived should disappear!

Distributing Branch Explorer filters to your colleagues

Now you have your Plastic SCM installation set up to hide those annoying branches, but what about your peers? If you don’t have any (sorry about that), or you work in a completely distributed setup, then your only option is copying the relevant sections of your branchexplorer.cfg file, and pass them through email, Slack or something similar (don't worry, the format is really easy to understand!) This Branch Explorer configuration file is located at:

  • Windows: %LOCALAPPDATA%\plastic4\branchexplorer.cfg
  • macOS and GNU/Linux: $HOME\.plastic4\branchexplorer.conf

But if you work in a completely centralized scenario, Plastic SCM's Global Configuration comes in handy to automatically set up these filters in your peers' machines, regardless of their operating system, without them having to lift a finger.

But let me tell you the basics of Global Configuration – just this once.

The plastic-global-config is a special repository that you can create manually. When your Plastic client (either GUI or CLI) needs to load a configuration file, after looking for it in the usual places (workspace, plastic4 directory, and so on), it looks for it in a special, invisible workspace pointing to that plastic-global-config repository. Before trying to load any configuration from it, the client runs a fast update, so it always has the latest content, and so the files you add to it are available for everybody, instantly.

So, now that you know that... how do we distribute our branchexplorer.conf (careful with the extension here!) through plastic-global-config? Easy:

  1. Create the plastic-global-config repository (if it does not exist yet).
  2. Create a workspace pointing to it.
  3. Because branchexplorer.conf affects all repositories, create a directory called allrepos at the root of the workspace.
  4. Copy to the \allrepos directory the branchexplorer.conf file you want to distribute.
  5. Checkin this change.

If you are a CLI hacker, these are the steps for Windows, so you can get the grasp of each operation:

C:\wkspaces\> cm repository create plastic-global-config
C:\wkspaces\> cm workspace create config config
C:\wkspaces\> cd config
C:\wkspaces\config\> cm switch br:/main@plastic-global-config
C:\wkspaces\config\> md allrepos
C:\wkspaces\config\> copy %LOCALAPPDATA%\plastic4\branchexplorer.cfg allrepos\branchexplorer.conf
C:\wkspaces\config\> cm add -R *
C:\wkspaces\config\> cm ci -c="Add branch explorer global configuration"

So, what happens if your colleagues already have their own Branch Explorer filters configured? Will they be overridden with the Global Configuration? That's a great question. Long story short, their filters won't be overridden, nor will they be duplicated if they already have defined a filter with the same effect that one that you are distributing. Your Global Config filters and their local ones will merge. If the filters are good there shouldn't be any issue but keep an eye on conflicting filters that might create weird filtering in the Branch Explorer (for example, opposite conditions).

Sadly, the externaltools.conf file is not currently distributed through plastic-global-config. Is it something that you'd want to have? Feel free to leave a feature request in our UserVoice!

Wrapping up

Branches are central in our workflow, but don't necessarily have to be on yours to take advantage of archiving. In this blogpost, we introduced the attribute as a way of adding metadata to objects. Then, we used that metadata to point out branches that are no longer necessary. Then, we hid them from view in the GUI using a little bit of cm find and the external tools. Finally, we learnt a little bit about plastic-global-config and how to configure these filters for all your peers, at once.

As always, if you had any problem following these instructions, please don't hesitate to contact us! Twitter, a comment below, an email... we'll reach to you as soon as possible, I promise!

Sergio Luis
After an intense internship at Codice during spring and part of summer 2015, I joined the ranks of Plastic SCM as junior developer.
I already contributed code to the Plastic REST API, the HAL Slack bot that controls our CI system, migrated our internal main server to "new" hardware, coded an Android repo browser and hacked wifi-direct for the upcoming Plastic version.
You can reach me at @_sluis_.

0 comentarios: