Kategorien
Allgemein

Thoughts on git commits

Over the last few days I read articles about git commits and commit messages here, here and here. I don’t know if the article are new or years old, but I started to reflect on my usage of git and how I create my commit messages.

First of all, there are two differences I make: personal repositories that only I work on and that I won’t share with anyone else (although they might be public on github) and professional repositories that I share with others or where I work together with a team. They have different rules in my head, and so my commit messages look a lot different. On the other hand, handling of branches is not different at all. So, let’s go over how I use branches first.

I have one rule: Use a branch for everything.

First exception to that is fixing a typo, if it’s changing just on letter.
Everything else goes into a branch first. This is useful if I decide to commit a bunch of nonsense and drop all those commits again after recognizing that I totally lost track of the goal I set out to achieve or if I want to rewrite history to please my esthetical brain. I also tend to rewrite commit messages a lot after reading them in my git log. Usually my workflow goes like this:

  • Starting working on a bugfix or feature, create a branch.
  • The initial commit has a message that follows the pattern described here.
  • Commit a bunch of stuff, sometimes WIP commits which are not a fully functional thing on their own, but just a savepoint.
  • Interactive rebase when I’m done to re-order, squash or split commits. Goal is to bring the number of commits down as much as I can without sacrificing understandability. This might end up as one big commit, but for reviews I like to keep things a bit more separated – makes it easy to follow my thoughts. I can always squash everything into a single large commit before merging.
  • Push to remote.
  • Get a review (automated for boring stuff, from a real person for the interesting things).
  • Maybe rebase on branch master to avoid garbled history on the main branch.
  • Merge with --ff-only to make sure the history is clean.

I like the branch model described in the post “A successful git branching model”, but I can also work with just a master branch – as long as I can have my own feature branches on remote while working, to have the CI do all the automated checks and run my tests.

Now, let’s talk about commit messages. First my rules for professional repositories which I share and work with other people. Most important rule: The first line is a short summary of what the commit does. And I’m not talking about “Fix stuff” and the like. I also like to include a reference to the issue tracker on the first line, at the start of the message. If you generate your changelogs from git history, this will make it a lot better.

The rest of the message is a description of WHY the commit does what it does and details about the most important parts of the change. This should read like the summary at the start/end of a non-fiction book with the big picture overview. The message should also answer these questions (see this post):

  • Why is it necessary?
  • How does it address the issue?
  • What effects does the patch have?

This way your tools display nice to read, descriptive one-liners and you can read the summary chapters if you want to or if you’re looking for a specific commit.

For personal, non-shared repositories I’m less strict. If you look into the git log for this blog, for example, there is a lot of “new post” and
“fix link to heroku” going on. Because it’s also not sourcecode, I don’t really care that much. Nothing breaks if I fix image URLs, no money is lost by a business and there simply isn’t much that I need to write down for myself for reference later on if I add an image to a post. ‍♂️ Most of the changes in this commits are perfectly described by a short one-liner message that says “new post”, for example when I add this article to my blog.

Ok, before I start rambling now about messy git histories on the main branch and how people don’t follow simple naming patterns on branches or how nobody seems to know how to squash commits, I’ll just stop here. There are some good articles linked, you should read them and try to write a better commit message for your next commit.

Kategorien
Allgemein

Neue Anbauteile fĂĽr mein Motorrad

Ich fahre ja seit einigen Jahren eine Honda Hornet PC41, an der ich bisher nicht ein Teil verändert habe. Jetzt habe ich mir kurz entschlossen neue Spiegel gekauft, weil ich schon immer die nach unten montierten kleinen RĂĽckspiegel cool fand – und bei den aktuell montierten Spiegeln muss ich immer ein biĂźchen meinen Kopf bewegen, um eine gute Sicht zu haben. Wie auch immer, das hier sind die Spiegel:

RĂĽckspiegel "Montana 2"

Bestellt habe ich die Spiegel “Montana 2” bei Louis. Und weil einer der Griffe schon etwas locker sitzt und die Lenkerenden auch schon ein wenig rostig sind, habe ich mir auch gleich neue Griffe “Racing”
dazu bestellt:

Griffe "Racing"

Jetzt muss ich nur noch die Montage hinbekommen…

Kategorien
Allgemein

Google verwendet Daten aus unseren Smartphones

TL;DR OH NOES! Wer hätte das gedacht?

The Intercept schreibt in “Google’s Sidewalk Labs Plans to Package and Sell Location Data on Millions of Cellphones” folgendes:

Most of the data collected by urban planners is messy, complex, and difficult to represent. … A new initiative from Sidewalk Labs, the city-building subsidiary of Google’s parent company Alphabet, has set out to change that.

…

The program, known as Replica, offers planning agencies the ability to model an entire city’s patterns of movement … a comprehensive view of how, when, and where people travel in urban areas.

…

In recent months, transportation authorities in Kansas City, Portland, and the Chicago area have signed up to glean its insights. The only catch: They’re not completely sure where the data is coming from.

Dazu kann ich nur sagen, dass solche Dinge kaum eine Ăśberraschung sein dĂĽrften. Selbst die mittlerweile untergegangenen Hersteller von Navigationssoftware haben solche Daten erhoben, um ihre Produkte zu verbessern. Google hat das ganze in bester Google-Manier eben weltweit und technisch sehr viel besser gemacht. Der
Großteil der Menschen hat ein Smartphone und wird damit zu einem Sensor. Und Googles Android Betriebssystem ist auf dem Großteil dieser Geräte installiert. Wer heute noch davon überrascht wird, das Google so viele Daten wie möglich sammelt, der hat wirklich in den letzten 10 Jahren geschlafen oder die Entwicklung bewußt verdrängt.

Und wenn die gesammelten Daten zur Planung von Städten eingesetzt werden, statt zur Vermarktung von Werbeanzeigen, dann bin ich ehrlich gesagt dafür. Wenn dann die Planung der Verkehrswege für Fussgänger oder Radfahrer besser wird, dann würde ich sogar eine dedizierte App dafür installieren.

Wenn wir solche Daten nicht fĂĽr diese Art von Projekte einsetzen, dann sollten wir unsere Smartphones am besten ganz abschalten und wieder auf die guten alten Papierkarten zur Navigation umsteigen. Und trotzdem wĂĽrden Apple, Facebook und Google weiter alles sammeln, was sie bekommen – nur halt ausschliesslich fĂĽr ihren eigenen Profit.

Trotz aller Google-Skepsis halte ich den Konzern noch am ehsten fĂĽr fähig – und bereit – die gesammelten Daten fĂĽr solche Projekte einzusetzen. Ich kenne z.B. kein einziges Projekt von Facebook, dass irgendwas fĂĽr die Allgemeinheit verbessern will, statt nur
die Userbindung an die eigenen Projekte… Falls jemand Beispiel hat, bin ich sehr daran interessiert.

Kategorien
Allgemein

Video Thumbnails unter Windows erstellen

Vor ein paar Tagen wollte ich zur Unterscheidung von Video-Duplikaten aus allen Videodateien in einem Verzeichnis Thumbnails erstellen. Vorzugsweise aus der Mitte der Videos, damit ich auf
einen Blick sehen kann, welche Dateien das gleiche Video enthalten. Leider ging das nicht einfach aus den Metadaten, deshalb musste ein kleines Skript her:

@echo off
for /r %%i in (*.m4v) do "c:Program Files (x86)VideoLANVLCvlc.exe" "%%i" --rate=1 ^
  --video-filter=scene --vout=dummy --aout=dummy --start-time=240 --stop-time=241 ^
  --scene-path="%%~pi" --scene-format=png --scene-ratio=24 --scene-prefix="%%~ni" vlc://quit

Das Skript verwendet VLC, um einen Thumbnails bei Sekunde 240 zu erstellen. Seltsamerweise wird auch noch ein Thumbnails bei Sekunde 0 erstellt, der bei jedem Video natĂĽrlich schwarz war.

Ein paar Anmerkungen zum Skript:

  • Es werden alle M4V Dateien im Verzeichnis verarbeitet.
  • Der Thumbnail wird mit dem gleichen Namen (wird per %%~ni in der Schleife erzeugt) im PNG-Format erstellt.
  • Die Thumbnails werden im gleichen Verzeichnis (per %%~pi in der Schleife erzeugt) abgelegt.

Vielleicht hilft das Skript ja dem ein oder anderen bei ähnlichen Aufgaben.

Kategorien
Allgemein

EindrĂĽcke aus Red Dead Redemption 2

Mittlerweile habe ich ein paar Stunden in Red Dead Redemption 2 verbracht und muss sagen, das Spiel ist genau für mich gemacht: Kein Zeitdruck, viel zu sehen und trotzdem schöne Missionen, wenn
man sich mal wieder irgendwo verlaufen hat. Hier ein paar  Impressionen:

My journey in Red Dead Redemption 2 on PS4

Das Album liegt bei imgur statt bei flickr, da ich mal was anderes ausprobiere. Ich werde von Zeit zu Zeit neue Screenshots hinzufĂĽgen.

Kategorien
Allgemein

How to hardware reset the new Oura ring

On the weekend my Oura ring didn’t connect to the app anymore when I wanted to see my HRV in the morning. I tried the troubleshooting steps from the FAQs but without any change, so I wondered how to actually reset the ring. There is no UI, no buttons, no reachable connectors at all.

The support helped me out, and here is a short description of the hardware reset procedure for the Oura ring:

  • Place the ring on the (powered) charger. Make sure the charging LED is glowing.
  • Hold the ring in place with your finger.
  • Tap the charger + ring on the table a couple times.
  • Wait a minute.
  • Check if the ring is showing up in your app again.

Hope this helps.

Kategorien
Allgemein

Endlich da: Mein Oura Ring

Vor einigen Monaten habe ich mir nach einer Phase der Abstinenz wieder einen Fitness Tracker besorgt. Diesmal ist es ein Oura Ring geworden, kein Fitbit mehr. Vor allem haben mich dazu der Formfaktor, die Herzfrequenzvariabilitäts- und Temperaturmessung bewogen. Heute kam das gute Stück dann endlich an.
DSC_0137-01

Ich habe bis jetzt noch keine Ringe oder anderen Schmuck getragen. Vor ein paar Wochen habe ich den Plastikdummy für die Größenmessung für einen Tag getragen und mich relativ schnell dran gewöhnt. Der echte Ring fühlt sich natürlich viel besser an, hat rundere Kanten und glatteres Material. Während des Trainings werde ich ihn natürlich abnehmen, denn eine Langhantel- oder Klimmzugstange dürfte selbst den härtesten Ring (oder den weichesten Finger) über kurz oder lang schaffen…

In der App gibt es bis jetzt noch nicht viel zu sehen, die richtigen Einblicke werde ich morgen früh bekommen. Über Nacht zeichnet der Ring meine Körpertemperatur und die Herzfrequenz auf. Morgens soll man dann gleich über die Herzfrequenzvariabilität eine Readiness für den Tag bekommen, d.h. wie ausgeruht man ist und wie anstrengend z.B. das Training sein kann. Ausserdem bekommt man natürlich die “üblichen” Daten zum Schlaf und die Aktivitätsübersicht über den ganzen Tag.

Wenn die ersten Daten da sind, werde ich diesen Post noch einmal ergänzen.

Kategorien
Allgemein

Qutebrowser userscript for TT-RSS

After the recent mishap of Firefox I switched to qutebrowser on Linux and Windows. As an i3wm user, I feel right at home – but I do miss the synchronisation between machines and my mobile. But I guess I have to live with that inconvenience for the moment.

One thing I can not live without is a quick bookmark to share articles via my ttrss installation. If you are interested, you can find my shared articles as a RSS feed here. I update the feed almost every day when I find something interesting.

Anyway, because qutebrowser does not have a quick bookmark toolbar, there is no way to quickly share an interesting URL. But fortunately, one can extend qutebrowser via userscripts – which are simple shell scripts receiving a couple variable like URL, title and selected text.

#!/bin/bash
echo "open -t https://MYHOST/PATH/TO/TTRSS/public.php?op=sharepopup&content=${QUTE_SELECTED_TEXT}&title=${QUTE_TITLE}&url=${QUTE_URL}" >> "$QUTE_FIFO"

The userscript can be executed with the following command:

spawn --userscript ttrss

It will execute the shell script and open a new tab in qutebrowser showing the ttrss share page. To make it even more convenient, I decided to bind the userscript to the key combination tt with the following command:

bind tt spawn --userscript ttrss

Now I can simply press tt when I read a nice article and share it to my ttrss feed.

Kategorien
Allgemein

Enable request logging in Jetty 9.1

Today I wanted to have a more detailed look into the requests coming into one of my applications using Eclipse Jetty. While it is easy enough to see incoming requests by enabling logging for class org.eclipse.jetty.server.Server (via the standard java logging API or SLF4J), adding a method to log incoming request headers is on a different level.

After digging around in the documentation and the sourcecode for a while, this is what I came up with:

// Create a server, but do not start it. This would prevent adding
// handlers later
Server server = JettyHttpContainerFactory.createServer(baseUri, null, null, false);

HandlerCollection handlers = new HandlerCollection();
// request log handler
RequestLogHandler requestLogHandler = new RequestLogHandler();
RequestLog requestLog = new Slf4jRequestLog();
requestLogHandler.setRequestLog(requestLog);
RequestLog traceLog = new Slf4jRequestLog() {
  @Override
  public void log(Request request, Response response) {
	  LOG.info("*************************************");
	  try {
	    Enumeration<String> headerNames = request.getHeaderNames();
	    while(headerNames.hasMoreElements()) {
		    String headerName = headerNames.nextElement();
		    String headerValue = request.getHeader(headerName);
		    LOG.info("{}: {}", headerName, headerValue);
	    }
	    // only dump the request body if we can reset the inputstream
	    if(request.getInputStream().markSupported()) {
		    request.getInputStream().mark(Integer.MAX_VALUE);
		    LOG.info(IOUtils.toString(request.getInputStream()));
		    request.getInputStream().reset();
	    } else {
		    LOG.info("Can not dump request body, because it can not be reset");
	    }
	  } catch (IOException e) {
	    LOG.warn(e);
	  }
	  LOG.info("*************************************");
  }
};
requestLogHandler.setRequestLog(traceLog);
// handler for real requests
final JettyHttpContainer containerHandler = ContainerFactory.createContainer(JettyHttpContainer.class,
	new RestResourceConfigWithSpringSupport("application-context.xml", MyServiceClass.class));
// add all handlers
handlers.setHandlers(new Handler[]{requestLogHandler, containerHandler});
server.setHandler(handlers);

server.start();

Note that I’m using a RestResourceConfigWithSpringSupport, but that doesn’t have to be the case. The main point for me was to create the JettyHttpContainer myself and not use the one created by a different call to JettyHttpContainerFactory.createServer(...). This way I can see at least the HTTP headers coming into my application. I’d prefer to see the body too, but I didn’t want to spent the time for it right now.

If anyone knows a way to wrap the request InputStream into a re-readable option, please let me know.

Kategorien
Allgemein

Run Feedbin in your local Kubernetes cluster

After listening to the Changelog Podcast, episode 240 today I wanted to run Feedbin in a local kubernetes cluster. I’ll skip the installation of kubernetes for now, but you can read about setting kubernetes up with minikube elsewhere. For this short article, I’ll just describe the commands that are needed to get a first version of Feedbin up and running in your local cluster.

First of all, create a Postgres database:

kubectl run postgres --image=postgres --port=5432
kubectl expose service postgres --type=NodePort

Because this is purely for demonstration, I’m not setting a custom postgres username nor password. Don’t do this if you want to run Feedbin for real.

The first command actually created the container to run postgres, the second command created a kubernetes service for it. From the docs:

A Kubernetes Service is an abstraction which defines a logical set of
Pods and a policy by which to access them – sometimes called a micro-service. The set of Pods targeted by a Service is (usually) determined by a Label Selector (see below for why you might want a Service without a selector).

As an example, consider an image-processing backend which is running with 3 replicas. Those replicas are fungible – frontends do not care which backend they use. While the actual Pods that compose the backend set may change, the frontend clients should not need to be aware of that or keep track of the list of backends themselves. The Service abstraction enables this decoupling.

So now we have a postgres service which can be used by other pods in the cluster. You can always check the status of your pods with the following command:

$ kubectl get pods
NAME                              READY     STATUS    RESTARTS   AGE
postgres-1342422565-hzgx9         1/1       Running   0          1m

Next is running Feedbin and I’m using an existing docker image scavone/feedbin:

kubectl run feedbin --image=scavone/feedbin --port=9292 --env POSTGRES_USERNAME=postgres --env POSTGRES=postgres --env POSTGRES_PASSWORD=
kubectl expose deployment feedbin --type=NodePort

Using minikube you can now open a browser for your Feedbin installation:

minikube service feedbin

This should open your default browser and show the Feedbin login.

As always, if you have questions or corrections, please leave a comment or send me an email.