Creative Code Management

tutorial

One of the things that’s plagued me since I’ve been doing creative coding is managing the code I use to create images and animations (or whatever else). Of course, standard source control management comes into it in a big way. I’ve been using git for ages. I remember having arguments with coworkers who refused to see how git was better than SVN (at least they had moved off of CVS). So yeah, you put your code in a repo and you check in your changes, etc.

But most source control workflows are really made for building applications. You decide on a feature, you make a branch, you do the work over a few hours or days or whatever, and you merge your code in. Or the same for a bug.

In creative coding though, the update/render cycle is a few orders of magnitude faster than that.

  • Change a variable, render.
  • Change it a bit more, render.
  • Change another variable, render.
  • Put the first one back to where it was, render.
  • Ah! I like that one. Publish the image to twitter, or a website or wherever.
  • Change some other variables around, render a bunch of times.
  • Find another one you like, publish that image.
  • Repeat several times.
  • Done for the day, check in the code to git.

The problem is, tomorrow or next week or six months from now, you want to recreate that first image you published. What were the exact variable values you used to create it? Who knows? Even if you didn’t change the code, it might be nearly impossible to rediscover the exact parameters to recreate a specific image.

Git branches are too cumbersome for this fast workflow. You can make a new branch when you find some parameters you like, but as soon as you change some other values, that branch no longer represents that first image. There are ways to work around this, but again, it gets cumbersome. But I finally figured out a good solution, along with a custom shortcut that I’m really happy with: Tags.

A git tag is a permanent, unchanging reference to a specific point in time of your code base. Tag your code at a certain point and you can always get back to that exact point. It’s never going to change unless you delete the tag and create a new tag with the same name.

So, when you come up with an image that you want to save and publish, you do the following:

  1. git add . to add all the changed files.
  2. git commit -m <some message> to commit those changes.
  3. git tag <some name> to create the tag to that exact commit.
  4. git push to push it to the main repo (if you have one).
  5. git push --tags to push the tags to the main repo.

All good, but that’s still five steps. Still a bit cumbersome. So I made a bash script that does all this in one shot:

#!/bin/bash

git add .
git commit -m $1
git tag $1
git push
git push --tags

I named this file tagit, made it executable (chmod +x tagit) and put it in my path. If you’re not totally up on shell syntax, $1 stands for the first argument given when the script is called. So now, when I want to save the state of my work, I jump to a shell and type tagit coolpicture or whatever tag name I want to give it.

This adds the files, commits them using coolpicture as a commit message, tags the commit with the same label and pushes to the main repo, and then pushes the tags to the main repo.

Now, six months from now when you want to see the settings you used for that cool picture, you just say git checkout coolpicture and there you are. Obviously, you want to name your tags something a bit more memorable. Some kind of timestamp or sequence is a good idea. I usually name the image or animation file the same as the tag name, so 210801a.png is the image that was created in the tag 210801a. You could even automate this if you wanted, to generate that image/tag name and rename the image when it creates the tag.

One other point that I know someone will ask.

Can’t you just say:

git push --tags

and ignore the

git push

?

You can if you want. It will push the current code that is in this tag to the main repo. But it will not push the current code in the current branch to that remote branch. So your remote master branch (or whatever branch you are on) will not line up with your local branch. But your tag will still be saved as expected. It’s up to you which behavior you want. Maybe you only want to push the tag, not commit to the branch at that point. Or maybe you want to save to the branch and the tag every time.

Also, you could change:

git push --tags

to:

git push origin $1

This will only push the specific tag you just created. There might be slight advantage to this in terms of speed. I suspect not. But, if you have other local tags hanging around that maybe you don’t want to push, you should go this route.

Anyway, use this script as is, or change it to fit your needs. Hopefully it saves you some time and frustration one day.