Skip to content

Examples of git-ZMF interaction

Before we use git to interact with ZMF, all components taking part in the exchange between a ZMF package and a local git repository must have already been checked out into the ZMF package. The exception to this rule is when the components being pushed up from the local repo are new to ZMF.

The ZMF subsystem used for these examples is U825ALL.

A zowe zmf profile called d001.u825all has been created which targets the REST services base_path/zmfrest. In the ZMF REST api TomCat stc, the web app called zmfrest has startup parameters that point it to the U825ALL ZMF subsystem.

This is the sample package we will be working with:

            STAGE: STEV001590 Components                    Row 1 to 9 of 9
Command ===>                                                Scroll ===> CSR
Name       + Type   Status      Changed             Procname    User Request
CBLCPY01    CPY     ACTIVE      20210826 080231                     WSER58
CBLCPY02    CPY     ACTIVE      20210812 035540                     WSER58
CBLCPY03    CPY     ACTIVE      20210812 042249                     WSER58
CBLCPY04    CPY     ACTIVE      20210809 034448                     WSER58
CBLCPY05    CPY     ACTIVE      20210729 023109                     WSER58
CBLCPY06    CPY     ACTIVE      20210811 022913                     WSER58
CBLCPY07    CPY     ACTIVE      20210812 035851                     WSER58
CBLPGM01    SRC     ACTIVE      20210826 075600     CMNCOBE         WSER58
CBLPGM02    SRC     ACTIVE      20210715 032617     CMNCOBE         WSER58
******************************* Bottom of data ******************************
It only has a handful of components but it’s enough to work through the git/ZMF functions.

Note

Because we will not be using a "component filter" on these components, all of them will be eligible for use by the local git repo.

Case 1: Create a local clone of the contents of a ZMF package

This example creates a new git local repo populated with the contents of the package.

First create a directory into which you will be cloning the package. The action of git cloning will automatically create a git repo in the directory you point the clone at. In this example I will clone this package into a directory called ‘sandbox’ .

At a command prompt, navigate your way to the directory in which you will create the ‘sandbox’ clone.

Then issue the following git command:

git clone ZMF://d001.u825all/STEV1590 sandbox

The source location for the clone is ZMF://d001.u825all/STEV1590 (or STEV001590, either will work). Let’s break this down.

Starting this location with ZMF: lets git know that it must use a remote protocol helper to access this repository. It looks for an executable called git-remote-ZMF to do the actual remote access. This is the main executable that we provide.

Everything after the ZMF: is then interpreted by git-remote-ZMF.

The name after the // must be a zowe zmf profile name defined on the local machine. This is the profile that the zowe zmf cli commands issued by the ZMF protocol helper will use to route, firstly, to the ZMF RESt api Tomcat stc, and then on to the U825ALL ZMF subsystem.

After the profile name we have a / delimiter followed by the package name. The output in the command prompt window looks like this:

D:\GitDev\ZMF\clonedRepo>git clone ZMF://d001.u825all/STEV1590 sandbox 
Cloning into 'sandbox'...
progress : querying ZMF package STEV001590 for eligible components ... 
progress : extracting 9 components from ZMF package STEV001590 ...
progress 1 of 9 CBLCPY05.CPY -> D:\GitDev\ZMF\clonedRepo\sandbox\CPY\CBLCPY05.cbl 
progress 2 of 9 CBLCPY04.CPY -> D:\GitDev\ZMF\clonedRepo\sandbox\CPY\CBLCPY04.cbl 
progress 3 of 9 CBLCPY06.CPY -> D:\GitDev\ZMF\clonedRepo\sandbox\CPY\CBLCPY06.cbl 
progress 4 of 9 CBLCPY02.CPY -> D:\GitDev\ZMF\clonedRepo\sandbox\CPY\CBLCPY02.cbl
progress 5 of 9 CBLCPY07.CPY -> D:\GitDev\ZMF\clonedRepo\sandbox\CPY\CBLCPY07.cbl 
progress 6 of 9 CBLCPY03.CPY -> D:\GitDev\ZMF\clonedRepo\sandbox\CPY\CBLCPY03.cbl 
progress 7 of 9 CBLCPY01.CPY -> D:\GitDev\ZMF\clonedRepo\sandbox\CPY\CBLCPY01.cbl 
progress 8 of 9 CBLPGM02.SRC -> D:\GitDev\ZMF\clonedRepo\sandbox\SRC\CBLPGM02.cbl 
progress 9 of 9 CBLPGM01.SRC -> D:\GitDev\ZMF\clonedRepo\sandbox\SRC\CBLPGM01.cbl 
progress complete for ##ZMF## CMNI STEV001590 2022-01-17 17:14:33.331505

D:\GitDev\ZMF\clonedRepo>

If you see something like this...

D:\GitDev\ZMF\clonedRepo>git clone ZMF://d001.u825all/STEV1590 sandbox 
Cloning into 'sandbox'...
component-filter file has no entries for our target ZMF subsystem

It means you have defined a global component filter file in the GIT_ZMF_FILTER location (such as a limited clone to a different repo) and it contains no entries for the target we wish to work with.

Either delete this file (zmf-component-filter) or add an appropriate entry to it.

When the clone has completed you will find a directory called sandbox has been created which has three subdirectories. The .git subdirectory is "hidden", and this is where git places all its tracking and control information. We also use the directory structure below .git for ZMF operations. The other two subdirectories are CPY and SRC – in fact there will be as many of these subdirectories created as there are library types being used in the package.

Note the ‘progress complete’ message from the git clone. This string is used by git to create a commit point for the clone and it contains a number of pieces of information:

  • ##ZMF## makes it easy to spot that this is a ZMF related commit point.

  • CMNI is the subsystem identifier for U825ALL.

  • STEV001590 is the package which forms the remote repository for this clone .

  • A timestamp for the clone operation is displayed below the package.

To issue git commands related to this newly create local repo you must be inside the top level directory, so you can use cd to change to the sandbox directory. Then you can issue git commands. For example, the git log command lists logged activities.

D:\GitDev\ZMF\clonedRepo\sandbox>git log
commit a8cd39838ce6e6371ae03e48fa81d5e13b68c0ed (HEAD -> master, origin/master, 
    origin/HEAD, refs/ZMF/origin/heads/master)
Author: Me <[me@microfocus.com](mailto:me@microfocus.com)>
Date: Mon Jan 17 18:14:33 2022 +0100

    ##ZMF## CMNI STEV001590 2022-01-17 17:14:33.331505

D:\GitDev\ZMF\clonedRepo\sandbox>

The commit point created by the clone operation is given a sha1 hash token (the first few characters are a8cd39…) that uniquely identifies the event and its collection of files to git. It is also given a more readable comment (or "commit message") that is generated by the helper at the end of the clone operation.

When a clone operation is performed, the ZMF git protocol helper supplies git with the components it wants to be ‘cloned’ (via zowe zmf commands) and git takes over from there. We also build rows for each component in the local ZMF meta-database. This information is used when reconciling local components with those up at the package as we will see in following examples.

Case 2: Synch local development on our cloned repo with the target ZMF package

At this time, we have made changes to a source component in our local (cloned) repo.

For example, we have updated CBLPGM01 and performed whatever local building and testing we needed to do. We now want to send the changes back to the ZMF package.

In order to see this at work, you can use whatever desktop editor you like to update CBLPGM01. You then need to add the changes to git and then commit them.

We are now in a position to push these changes back to ZMF. In this example we have no concurrent development clashes and this proceeds quite simply:

D:\GitDev\ZMF\clonedRepo\sandbox\SRC>git push origin master 
To ZMF://d001.u825all/STEV1590
    a8cd398..fc630c6 master -> master

Note

The origin is the target of the push (which has been defined by git to be our ZMF: reference). And master is the name of the local git branch we are pushing from.

If you look on ZMF on the mainframe you should see the changes to CBLPGM01 are now in the package and the source component is in INCOMP status. If you are using SSV (and why wouldn’t you be ?) you can use VC to see the SSV delta:

                                Version Control                            Row 1 to 17 of 17

Command ===>                                                                 Scroll ===> CSR

Type: SRC Package: STEV001590                                                   Staging view 
Component: CBLPGM01 +
    Level Prompt    Changed             User            Description

    STG             2022/01/18 02:37    WSER58          fc630c:change to CBLPGM01

Etc.

The SSV description is generated by the protocol helper and is made up of the first 6 chars of the git commit sha1 token (which is usually enough to uniquely identify any commit within a local repo) followed by as much of the ‘eyeball’ commit message that fits.

The component is currently in INCOMP status (it is a SRC component that needs to be built). This is where the sample zbld file can be used by the desktop user to initiate that build. For example:

D:\GitDev\ZMF\clonedRepo\sandbox\SRC>zbld CBLPGM01 SRC d001.u825all STEV001590 
zmf is "d001.u825all"
pkg is "STEV001590"
{
    "message": "CMN8700I - Component Build service completed", 
    "reasonCode": "8700",
    "returnCode": "00"
}

You should look at the zbld.bat file to see how this works. It has requested the build job to be submitted by ZMF.

We can do this again, but this time we will introduce a conflicting change made by a mainframe user directly in the package. So, we update CBLPGM01 using some other ZMF client. Then update, add and commit a conflicting change in the local repo.

We then attempt to push our change back to ZMF:

D:\GitDev\ZMF\clonedRepo\sandbox\SRC>git push origin master
conflict detected with target repository - use git fetch/merge or pull to 
consolidate latest changes in the remote repo
error: failed to push some refs to 'ZMF://d001.u825all/STEV1590'

So the process does not let you overwrite changes made to the component in the ZMF package. As the message says, you need to pull down the changes in the ZMF package to your local repo and merge them before re-attempting to push back to ZMF.

The next case will take a look at doing this.

Case 3: Pull down changes made in the target ZMF package and merge them with our local repo

There are two ways of pulling down and merging changes: fetch&merge, and pull. They both achieve the same objective, i.e. fetching changes from the remote repo (ZMF pkg in our case) and merging them into whatever we have in the local repo. The git pull command attempts to do this in one action. The git fetch command fetches the changed components from ZMF and places them into gits staging area (this is where your changes go when you git add them but before you git commit). The follow on git merge will attempt to merge the staged changes with your local repo and create a commit point.

It is at the merge stage (whether explicit as in fetch&merge, or implied in a pull) that conflicts are notified so you can resolve them.

We will now attempt a fetch and merge for the situation we were left with at the end of case#2, i.e. conflicting change in the CBLPGM01 component.

We start off by fetching updates from the ZMF package:

D:\GitDev\ZMF\clonedRepo\sandbox\SRC>git fetch origin
progress : querying ZMF package STEV001590 for eligible components ... 
progress : extracting 1 components from ZMF package STEV001590 ...
progress 1 of 1 CBLPGM01.SRC -> D:\GitDev\ZMF\clonedRepo\sandbox\SRC\CBLPGM01.cbl 
progress complete for ##ZMF## CMNI STEV001590 2022-01-18 12:07:53.199458
From ZMF://d001.u825all/STEV1590
    fc630c6..977f491 master -> origin/master

The fetch operation has decided that the only component that has changed is CBLPGM01. It has fetched the current version of the component from the ZMF package and placed it in the local repo as a separate branch (origin/master) commit point.

When two branches of a git managed development are different, unless you want to throw one of them away, you will need to merge them. So, to get the changes from ZMF into your local repo master branch you now proceed to attempt to merge these two branches.

D:\GitDev\ZMF\clonedRepo\sandbox\SRC>git merge origin/master 
Auto-merging SRC/CBLPGM01.cbl
CONFLICT (content): Merge conflict in SRC/CBLPGM01.cbl
Automatic merge failed; fix conflicts and then commit the result.

Note that it is assumed that the current branch (i.e. master) is being merged into.

In this case, as expected, the merge has failed due to conflicting updates. You need to resolve all indicated conflicts.

Git has actually updated your local repo but it has added indications as to the conflicts in the components affected. You must resolve the conflict, save your changes, and then use git add followed by git commit to finish up the merge of code from the ZMF package into the local repo.

At this point you can push the resulting merged update back to ZMF.

D:\GitDev\ZMF\clonedRepo\sandbox\SRC>git push origin master 
To ZMF://d001.u825all/STEV1590
977f491..245cf74 master -> master

Your merged change will now be in the ZMF package.

Version Control Row 1 to 19 of 19 
Command ===> Scroll ===> CSR
Type: SRC Package: STEV001590 Staging view 
Component: CBLPGM01 +
Level Prompt Changed User Description
STG 2022/01/18 04:33 WSER58 245cf7:resolve conflicts
-001 2022/01/18 03:47 WSER58 ISPF UI change
-002 2022/01/18 03:22 WSER58 fc630c:change to CBLPGM01

As already mentioned, the git pull command does the same thing as fetch&merge is a single operation. Unless you are wanting to perform several fetch operations before attempting a merge you are as well to just use pull. For example:

git pull origin

will fetch and merge from origin (i.e. our remote repo, the ZMF package) into the current branch of the local repo.

Case 4: Hook up a local repo to a ZMF package

We have already created a standard local git repo and we now want to hook it up to a target ZMF package instead of cloning the package.

In case#1 we created the local git repo by cloning the remote repo (i.e. the ZMF package) into it.

In this case we start with a repo that already exists and we now decide we wish to move components up to a ZMF package. Here we will look at sending new components to ZMF (if they already exist in baseline, they need to be checked out to the package first. Then you would pull them from there into your pre-existing local repo, merging conflicts as necessary).

With a pre-existing local repo (i.e. one set up before the need to interact with ZMF was identified), your repo may not be in the correct form. You need subdirectories for each ZMF library type with the relevant components stored beneath their library type subdirectory. In which case it may be easier to start a fresh repo and stage/commit components from your existing repo in that one. There are actually many ways of addressing this within git.

If you have a large pre-existing local repo, it is very possible that you will not want to send all of it to ZMF. If you want to send a certain subset to ZMF, you can use the component filter mechanism to restrict the eligible components.

In this example we will populate the local repo with a handful of copybooks and source components and then restrict the interaction with ZMF to a single source component and the copybooks it uses. (This is not a realistic scenario but good enough to demonstrate how this works.)

Here is the initial population of our new local repo (which is not, as yet, connected to ZMF in any way):

D:\GitDev\ZMF\localRepo\SRC>git commit -m "initial population" 
[master (root-commit) f2a78fa] initial population
5 files changed, 135 insertions(+) 
create mode 100644 CPY/NEWCPY01.cbl 
create mode 100644 CPY/NEWCPY02.cbl 
create mode 100644 CPY/NEWCPY03.cbl 
create mode 100644 SRC/NEWPGM01.cbl 
create mode 100644 SRC/NEWPGM02.cbl

I also need to create a ZMF package which will be the target for pushing component up from this local repo. I am still using U825ALL and I created package STEV001618 for this purpose.

OK, let’s say that I only want to consider NEWPGM01 and its two copybooks NEWCPY01 and NEWCPY02 as eligible for sending up to ZMF.

We need to create a file that looks like this:

{

    "componentFilter": [
        {
          "targetZMF": "d001.u825all",
          "applName": "STEV", "packageNumber": "001618", 
          "libType": ["CPY"],
          "componentName": ["NEWCPY01", "NEWCPY02"]
        },
        {
          "targetZMF": "d001.u825all",
          "applName": "STEV", 
          "packageNumber": "001618", 
          "libType": ["SRC"], 
          "componentName": ["NEWPGM01"]
        }
    ]
}

If this is placed here:

D:\GitDev\ZMF\localRepo\.git>dir
Volume in drive D is DATA
Volume Serial Number is 7440-DCE6
Directory of D:\GitDev\ZMF\localRepo\.git
18/01/2022 14:21 19 COMMIT_EDITMSG
18/01/2022 13:56 130 config
18/01/2022 13:56 73 description
18/01/2022 13:56 23 HEAD
18/01/2022 13:56 <DIR> hooks
18/01/2022 14:21 521 index
18/01/2022 13:56 <DIR> info
18/01/2022 14:21 <DIR> logs
18/01/2022 14:21 <DIR> objects
18/01/2022 13:56 <DIR> refs
18/01/2022 14:30 362 zmf-component-filter
6 File(s) 1,128 bytes
5 Dir(s) 1,977,709,088,768 bytes free
Then it will override any filter criteria placed at the ZMF_GIT_FILTER location.

In case#1, where the local repo was initialized via the git clone operation, git assigned the reference ‘origin’ to the url which denoted our target ZMF and package. In this case that won’t happen. We can continue to reference the url longhand or we can define our own reference. We could, of course, call it origin too but I will use a different name to show some variation. To assign the reference, issue:

D:\GitDev\ZMF\localRepo\>git remote add U825ALL ZMF://U825ALL/STEV001618

You can see the reference using…

D:\GitDev\ZMF\localRepo>git remote -v 
U825ALL ZMF://d001.u825all/STEV001618 (fetch) 
U825ALL ZMF://d001.u825all/STEV001618 (push)

Where we used ‘origin’ to denote the remote repo in previous cases, we will use ‘U825ALL’ in this case.

We are now ready to send our (limited subset) local repo components to the ZMF package:

D:\GitDev\ZMF\localRepo>git push U825ALL master 
To ZMF://d001.u825all/STEV001618
* [new branch] master -> master
After this we can see our subset of components in the target package:

STAGE:                  STEV001618 Components               Row 1 to 3 of 3
Command ===> Scroll ===> CSR
    Name        + Type  Status  Changed             Procname    User Request
NEWCPY01      CPY   ACTIVE      20220118 075638                 WSER58
NEWCPY02      CPY   ACTIVE      20220118 075638                 WSER58
NEWPGM01      SRC   INCOMP      20220118 075638                 WSER58
****************************** Bottom of data ******************************