Gak: Be more efficient with a Git repository
tl;dr: Gak is a terminal tool used along-side Git to automate product and workflow specific tasks that are not only Git-related, such as building and navigating to product folders. It enhances on Git to provide interactive wildcard-based switching of branches and provides commands for JIRA that allows to start work on an issue, log time and commit with a pre-formatted message header acquired from the issue’s information. It is extensible by the mean of one Python file per sub-command and is configurable on a per-repo and per-user basis.
The modern developer has access to many tools and IDEs that claim to simplify your development time and make the tough stuff simpler: manage your compiling toolchain, assist you in coding and abstract your source control. While software like Visual Studio Code and IntelliJ family of IDEs offer these helpers, I could not find myself to boot them up each time for doing what I wanted to do, especially in cases where the project files are generated by some tool like CMake or Premake. Furthermore, working most of the time with Git in a terminal, I just wanted something that could allow me to do simple repetitive tasks that I did everyday, each of them differently depending on the repository. I wanted it to be extensible, and I wanted it to be configurable.
Configuration files are expected at two different places: one is the
The
For those wondering, it’s made with Python and has been tested primarily on Windows while being used in Git-Bash.
Build with a configure pre-step (e.g., cmake, premake)
Now, I can start an issue from an up-to-date master (or from another branch specified with -b):
Finally, we have a branch protection systems where remote branches need to be in the namespace “dev”. This means that at times tasks that become bigger end up needing a remote branch (either for creating custom builds, or simply to make sure the work isn’t lost under catastrophic events). Adding the “dev/” prefix is just a command away:
Facilities for acquiring the two configurations files are provided too, along with JIRA connection.
The current way to install it is to clone the repository and install the package locally with
The tool was developed for Python 3, and I intend to keep it like so since Python 2 is, as most of you know, deprecated.
Note for Windows user: To make sure you are using Python 3, install using
In the hope that Gak will make your life a bit easier!
The modern developer has access to many tools and IDEs that claim to simplify your development time and make the tough stuff simpler: manage your compiling toolchain, assist you in coding and abstract your source control. While software like Visual Studio Code and IntelliJ family of IDEs offer these helpers, I could not find myself to boot them up each time for doing what I wanted to do, especially in cases where the project files are generated by some tool like CMake or Premake. Furthermore, working most of the time with Git in a terminal, I just wanted something that could allow me to do simple repetitive tasks that I did everyday, each of them differently depending on the repository. I wanted it to be extensible, and I wanted it to be configurable.
So I made one, and it’s called Gak.
It’s not an acronym, the word basically resembles Git. My thinking was that it’s easy to type without the keys being too close together on a QWERTY keyboard, and is used similarly to Git by typinggak subcommand arguments. In fact, for many builtin commands, it uses Git, for you.Configuration files are expected at two different places: one is the
gakconfig.d directory under the root of a repository, the other is a .gakconfig.json file in the user directory. Typically, platform and machine specific configurations such as IDE, means to open a file and credentials would go in the user configuration file, while repository configurations to know what file to open, directories to go to and what to build.The
gakconfig.d directory is expected to be versioned so that anyone can simply go into the repository and use Gak without additional effort (assuming the required configuration information are defined in the user configuration file, but the tool is informative enough to mention it if it can’t find what it is looking for). This also has the benefit of simplifies interaction with the repository since the configuration of a revision will be synced to the content of that revision.For those wondering, it’s made with Python and has been tested primarily on Windows while being used in Git-Bash.
But what can it do?
Simple stuff, really. But stuff I couldn’t simply drop into a repo and do before. Now, I can:Build with a configure pre-step (e.g., cmake, premake)
$ gak build -c my_product
Switch branch with a wildcard, choosing the branch I want interactively:/home/me/repo (master) $ gak switch keyword
0) branch_also_has_keyword
1) branch_with_keyword
Choose a branch (non-number to cancel): 1
/home/me/repo (branch_with_keyword) $
… or if there’s only one choice, I’m a single Enter keypress away:/home/me/repo (branch_with_keyword) $ gak switch keyword
Switch to branch 'branch_also_has_keyword'? (Yes: Enter, No: Any):
/home/me/repo (branch_also_has_keyword) $
Open products (e.g., binaries, IDE projects) using the appropriate command per-product and per-platform:$ gak open ? # Listing what targets are available in the current repo
Defined targets (default: my_product):
* my_product
* other_product
$ gak open # Opening the default
Opening my_product
$ gak open other_product # Opening a specific target
Opening other_product
Navigate to useful directories of a repository, invaluable for centralized repositories:/home/me/repo $ gak to ? # Listing what targets are available in the current repo
Defined targets:
* root => /home/me/repo
* my_product => /home/me/repo/src/my_product
* tests => /home/me/repo/tests/runner
/home/me/repo $ cd `gak to my_product`
/home/me/repo/src/my_product $ gakto root
/home/me/repo $ # gakto is an alias to cd `gak to $1`
With that covered, I could do most of the tasks I normally repeated over and over again quickly and without even thinking what my working directory is, so long as it’s somewhere under the repo’s root.And that still wasn’t enough
Looking at the repetitive tasks I was doing that had nothing to do with actually delivering code, I started looking at my interactions with Atlassian JIRA. We have some conventions with regards to JIRA and our source control data at work, and I felt all the time spent on following those by hand added up to… well too much. For example, we have branches named after its corresponding issue number, followed by some text derived from the issue title (e.g., “ABC-1234_some_task”). This convention actually led to my implementation ofgak switch since it brings the problem of having to remember the issue ID, which is what the terminal tab completion is interested about. We also have a convention for commit messages where the first line should be the issue ID, followed by the issue title. After a year of copy-pasting from JIRA, I had enough of it.Now, I can start an issue from an up-to-date master (or from another branch specified with -b):
/home/me/repo (any_branch) $ gak start ABC-1234
# Does:
# git checkout master
# git pull
Creating branch for issue: 'This is the issue summary'
Enter branch suffix name: my_task
# Does: git checkout -b ABC-1234_my_task
/home/me/repo (ABC-1234_my_task) $ # Now on ABC-1234_my_task, freshly branched from master
I can commit my work using the appropriate header without having to write it myself:/home/me/repo (ABC-1234_my_task) $ gak commit -m "My work summary"
# Yields message:
# | ABC-1234 This is the issue summary
# |
# | My work summary
And I add worklog for the issue currently being worked on:/home/me/repo (ABC-1234_my_task) $ gak log 30m
Succesfully logged 30m in issue ABC-1234
This last one is really useful to create habits of logging often in small batches for a more accurate picture of the time involved.Finally, we have a branch protection systems where remote branches need to be in the namespace “dev”. This means that at times tasks that become bigger end up needing a remote branch (either for creating custom builds, or simply to make sure the work isn’t lost under catastrophic events). Adding the “dev/” prefix is just a command away:
/home/me/repo (ABC-1234_my_task) $ gak mkdev
/home/me/repo (dev/ABC-1234_my_task) $ gak mkdev -t # One can also toggle it back
/home/me/repo (ABC-1234_my_task) $
That’s a lot of commands!
Indeed it is! But like any extensible tool, one can create its own and get it working quickly. Commands are discovered from the package’scommands folder, so adding a Python script with a class inheriting from GakCommand and register an instance using GakCommand.register_command. That also means you need to trust whatever you put into that folder, so taking the appropriate measure on the folder’s permissions is indicated.Facilities for acquiring the two configurations files are provided too, along with JIRA connection.
And can I get it now?
Yes! My plan is to be in open beta and have extra users to help me find bugs and improve the experience across platforms. There are probably additional use cases, and I would be happy to implement them (or review external implementation for inclusion in the builtin set).The current way to install it is to clone the repository and install the package locally with
pip install -e . When I’m confident enough, I will publish it on PyPi.The tool was developed for Python 3, and I intend to keep it like so since Python 2 is, as most of you know, deprecated.
Note for Windows user: To make sure you are using Python 3, install using
py -3 -m pip install e . Also, follow instructions (from the README.md) to prepend winpty in the gak script if you are using Git-Bash, otherwise input may sometimes hang.In the hope that Gak will make your life a bit easier!

Comments
Post a Comment