Technical Articles
Versioning your local objects using abapgit
Leveraging the power of git in SAP can be difficult since development is usually done by multiple developers on the same system. Unless you manage to get your developers their own systems, key concepts like branches will be next to useless because while you’re pushing the results into something meant for distributed development, you’re still doing centralized development.
“Hell is other people on your system” (Jean-Paul Sartre)
However, even on a shared system, you have one place where other people generally won’t bother you – your local objects. You can consider this your single-developer system where you can put prototypes or reusable code.
But since local objects are never transported, you no longer have them if you switch systems and if something were to happen to them, you can’t recover them easily. We can get around both of these issues by versioning them using git.
I’m going to assume abapgit is already set up on your system. It is not difficult, the simplest way involves copy-pasting a report.
From what I’ve seen, most people use the organization structure
my_username->literally_everything
for their local objects and don’t structure them further. This is equivalent to putting all your files on the desktop. Which I do, but who’s not a hypocrite these days.
You will need to create at least one top level package for this. Much better!
Your local objects are stored in the package $TMP, but since you don’t want to version everyone’s code, create a subpackage of $TMP. Name it whatever you like, just remember that local package names start with $.
You can also have multiple root packages/repositories, this depends on your use cases. I don’t know what code you have in there, that’s why I’m trying to get you to share it! You just need to:
Create a package
Create a Github repository:
Don’t forget the readme checkbox.
Open ZABAPGIT and click the +Online button
Now you will learn how to add some folder structure to your repo. Abapgit will let you version one top-level package per repository. Any subpackages will be converted to folders based on the folder logic.
There are two options:
- PREFIX – the child packages must begin with the parent package name. For example, $ZFH_PROTOTYPES is a valid subpackage of $ZFH according to prefix logic. This will create a folder named prototypes in the repository. Note that prefix logic won’t work correctly if you don’t follow the convention.
- FULL – folders will be named like packages.
You can create the subpackages and also change the folder naming convention at any time.
Now just add your objects and remember to commit updates every now and then.
=
At the very least, you get a backup and the ability to import your local objects to a different system. You also have a place where you can experiment with branching, pulling or resetting code to previous versions, which you might be afraid to do with your productive code.
I never thought of this use case. Will try it out! Is there any benefit to creating the package in $TMP compared to just creating a local package without a parent? I guess each developer will get a filtered view on their subpackages when displaying the $TMP contents?
Also I am very much used to losing all local objects at system copies, which won't be an issue anymore with this approach. Thanks!
Huh, you got me there. I thought all local packages were children of $TMP, but it is just what the package wizard prefills and your can in fact have no parent package for local packages.
However, now Eclipse doesn't display it in this list:
Seems like a good idea for some scenarios and to have different branches for new development, but in terms of versioning, will this help?
If an existing solution has a class ZCL_ABC, I wonโt be able to create another class ZCL_ABC as a local object to work on the next version of the solution as far as I know.
If some adjustments are made in the SAP core it would perhaps be possible to hack such a feature by using a per-developer local namespace (/$username/) and have the runtime use objects from the local namespace if they exist, otherwise the global objects!
So the ABAP runtime would for the statement โdata(shipment) = new ZCL_PSLO_SHIPMENT( )โ create an instance of class /$username/ZCL_PSLO_SHIPMENT if that class existed, otherwise create an instance of class ZCL_PSLO_SHIPMENT.
As mentioned, it would be a hack.
And it would of course also have to handle /$username/RL_NMSPC/CL_SOME_CLASS ๐ ... but even so I think that could perhaps be the path of least resistance to support parallel development.
No, unfortunately you can't have ZCL_ABC on the same system twice. But what you're describing is possible using proper architecture - you can have IF_ABC with ZCL_ABC1 and ZCL_ABC2 implementing it.
I sometimes stick a simple if uname into a factory to return a different implementation just for me, so I can try it out without breaking other people's stuff. Then I remove the if once I'm reasonably sure my implementation works.
This is of course only usable during development. Look into dependency injection if you need a less temporary solution.
That's true, but that's not really versioning (IMNSHO) ๐
And it would not solve the problem for reports, function modules, or any other object that can't have dynamic implementation resolution. So for instance if I wanted to extend a table with two new fields in the next version I don't really think it is a viable solution.
You're right. This is not something ABAP allows you to do - multiple versions of the same object simply can't coexist on the same system. The best you can do currently is work around it and stay tuned for news from the future :). This might take some time.
Some good news: the bleeding edge of ABAP already has an early working version of package management: https://www.youtube.com/watch?v=nGXeWWdZMJE