Archive for the 'Software' category

Use git reflog to split two squashed commits

published on February 08, 2019.

Today I was using interactive git rebase to squash some commits together to clean up the commit history of a git branch. At one point I went a bit overboard with it and squashed together two commits by mistake.

I’ve heard somewhere from someone that in git you pretty much can’t lose code because everything is in the git reflog. Today I decided to put that to the test.

Spoiler alert: git reflog saved the day.

The setup

We start with two separate commits, “Commit 1” and “Commit 2”:

> git hist
* c3fa1d6 -  (HEAD -> reflog-undo-squash) Commit 2 [Robert Basic 4 seconds ago]
* db73960 -  Commit 1 [Robert Basic 56 seconds ago]

Using git rebase -i HEAD~2 we start the interactive rebase for the last two commits:

pick db73960 Commit 1
f c3fa1d6 Commit 2

We choose to fixup “Commit 2” with “Commit 1”, which means that the second commit will be squashed with the first commit, discarding the commit message of the second commit.

Uh oh, that was a mistake, and our commit history now looks like this:

> git hist
* 786865f -  (HEAD -> reflog-undo-squash) Commit 1 [Robert Basic 5 minutes ago]

Our nice little “Commit 2” is now gone and before we start panicking and making more damage, let’s take a look at the git reflog to see what we have there.

Looking at the reflog

The git reflog right after the bad rebase shows us the following:

> git reflog
786865f (HEAD -> reflog-undo-squash) HEAD@{0}: rebase -i (finish): returning to refs/heads/reflog-undo-squash
786865f (HEAD -> reflog-undo-squash) HEAD@{1}: rebase -i (fixup): Commit 1
0a8f291 HEAD@{2}: rebase -i (pick): Commit 1
684d689 HEAD@{3}: rebase -i (pick): Commit 1
5761a21 HEAD@{4}: rebase -i (start): checkout 5761a21b0c0a1f12ab1c60bfef1f1d111ba699c0
c3fa1d6 HEAD@{5}: commit: Commit 2
db73960 HEAD@{6}: commit (initial): Commit 1

The thing at HEAD@{6} was the first thing that happened and the thing at HEAD@{0} is whatever is going on right now.

What we want the current state to be is the state before we started the rebase process, that is the state at HEAD@{5}. To do that we “reset” our state to that point in time:

> git reset HEAD@{5}

And now our git history is back to it’s pre-rebase state:

> git hist
* c3fa1d6 -  (HEAD -> reflog-undo-squash) Commit 2 [Robert Basic 15 minutes ago]
* db73960 -  Commit 1 [Robert Basic 16 minutes ago]

Note that even the commit shas are back to their pre-rebase values, db73960 and c3fa1d6.

The Atlassian git reflog tutorial goes into more detail, so make sure to read that as well.

Happy hackin’!

Tags: git, reflog, squash, rebase.
Categories: Development, Software.

Docker containers for PHP with

published on March 27, 2018.

This past weekend I was playing around on some pet projects and wanted to get up and running quickly. My initial reaction was to reach for a Vagrant box provisioned with Ansible. After all, that’s what I’ve been using for a really long time now.

Recently I’ve been also learning a bit more about Docker, so I figured maybe this pet project would be a good project to replace the standard Vagrant set up and go with Docker instead. When it comes to Docker, by now I believe I have a fairly good understanding of how it works and how it’s meant to be used in a development environment. I’ve learned a lot about it from Vranac, as well as poked around it on my own.

While trying to write a set of Docker files and Docker compose files for this project, I thought there must be an easier way to do this… And then I remembered that some time ago I came across a generator to generate Docker environments for PHP projects: As they state on their website: is a tool that will help you build a typical PHP development environment based on Docker with just a few clicks. It supports provisioning of the usual services (MySQL/MariaDB, Redis, Elasticsearch...), with more to come. PHP 7.1 is supported, as well as 7.0 and 5.6.

Click-click-click… done.

What I like about PHPDocker is that it takes a couple of clicks and filling out a couple of text fields to get a nice zip with all the things needed to get a project up and running. It has support for a “generic” PHP application, like Symfony 4, Zend Framework and Expressive, or Laravel, as well as for applications based on Symfony 23, or Silex. PHP versions supported range from 5.6 to 7.2 and a variety of extensions can be additionally enabled. Support for either MySQL, MariaDB, or Postgres is provided, as well as a couple of “zero-config” services like Redis or Mailhog.

The zip file comes with a phpdocker directory that holds the configurations for the specific containers such as the nginx.conf file for the nginx container. In the “root” of the zip there’s a single docker-compose.yml file which configures all the services we told PHPDocker we need:


#                          Generated on                          #
version: "3.1"

      image: mysql:5.7
      container_name: test-mysql
      working_dir: /application
        - .:/application
        - MYSQL_ROOT_PASSWORD=root
        - MYSQL_DATABASE=test
        - MYSQL_USER=test
        - MYSQL_PASSWORD=test
        - "8082:3306"

      image: nginx:alpine
      container_name: test-webserver
      working_dir: /application
          - .:/application
          - ./phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
       - "8080:80"

      build: phpdocker/php-fpm
      container_name: test-php-fpm
      working_dir: /application
        - .:/application
        - ./phpdocker/php-fpm/php-ini-overrides.ini:/etc/php/7.2/fpm/conf.d/99-overrides.ini

Run docker-compose up in the directory where the docker-compose.yml file is located and it’ll pull and build the required images and containers, and start the services. The application will be accessible from the “host” machine at localhost:8080, as that’s the port I defined I wanted exposed in this case. You can see that in the ports section of the webserver service.

One thing I noticed is that the mysql service doesn’t keep the data around, but that can be fixed by adding a new line to the volumes section of that service: ./data/mysql:/var/lib/mysql. The mysql service definition should now read:

      image: mysql:5.7
      container_name: test-mysql
      working_dir: /application
        - .:/application
        - ./data/mysql:/var/lib/mysql
        - MYSQL_ROOT_PASSWORD=root
        - MYSQL_DATABASE=test
        - MYSQL_USER=test
        - MYSQL_PASSWORD=test
        - "8082:3306"

Other than this, I didn’t notice any issues (so far) with the environment.

Inside the phpdocker folder there’s also a README file that provides additional information how to use the generated Docker environment, what services are available on what port, a small “cheatsheet” for Docker compose, as well as some recommendations how to interact with the containers.

Happy hackin’!

Connecting to MySQL 8

published on March 24, 2018.

I’ve used recently to generate a set of Docker files for a pet project and it had the option to use MySQL 8 and of course I went with that. The problem was when I wanted to connect to the database that was on this MySQL 8 server.

I had locally installed the MySQL 5.7 client version and when trying to connect to the MySQL 8 server it complained about a missing authentication plugin:

ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded:
/usr/lib64/mysql/plugin/ cannot open shared object file: No such file or directory

Turns out, in MySQL 8 this caching_sha2_password is the default authentication plugin instead of the mysql_native_password. This new authentication plugin is described in the documentation. I didn’t want to change anything in the MySQL docker image, so instead I decided to upgrade to MySQL 8 client on my Fedora. First I removed all traces of MySQL I had:

sudo dnf remove mysql

Then I installed the RPM from MySQL:

sudo dnf install

And finally installed the MySQL 8 client:

sudo dnf --enablerepo=mysql80-community install mysql-community-client

And now I can connect to the MySQL 8 server inside the Docker container:

mysql -P 8082 -h --protocol=tcp -utest -p test

Happy hackin’!

Tags: mysql, authentication.
Categories: Software, Development.

My OBS setup for recording screencasts

published on February 21, 2018.

Last year I started recording my contributions to open source. I wasn’t really regular, so today I published only the 9th episode: OSS Contribution 9.

Anyway, now I’m at the point where I am happy with the overall quality of the recording, both with the video and the audio and I want to write down the current setup so that I can recreate it in the future if I need to.

I’m using a Sennheiser GSP 300 headset and the microphone that comes with it. A really great product, I love it.

PulseAudio is responsible for the audio in my Fedora system. In the “Input Devices” settings of PulseAudio, I have set the “loudness” of the microphone to 25% or -35.94dB. I got there after a lot of trial and error.

As for the recording software, I was first using Zoom, which is a video conferencing and screen sharing tool. Start a meeting with myself, share screen, record. Buuut… I was never really happy with the audio.

I tried out Open Broadcaster Software, or OBS, last week. Again, after a lot of trial and error, I think I have the perfect settings given the hardware that I’m using. I picked it up from Swizec, he’s using it for his live coding sessions I believe.

“Settings > Output”: Output mode: simple, video bitrate: 2500, encode: software (x264), audio bitrate: 160, recording quality: indistinguishable quality, recording format: mp4. “Settings > Audio”: Sample rate: 44.1khz, the rest is all default. “Settings > Video”: Base resolution: 1920x1080, output resolution 1920x1080, the rest is default.

The most improvement came from setting filters on the microphone — “Mic/Aux > gear icon > Filters”. The first filter I added is “Noise Suppression” with a value of -17. The second filter is “Noise Gate” with a “Close Threshold” of -44, “Open Threshold” of -42, “Attack Time” 25ms, “Hold Time” 200ms, and “Release Time” 150ms. These last three might be the defaults, I’m not sure. I did play around with them.

Now, I said I’m happy with the audio, but I know it can be much better. One, I need to speak louder, and two, if these screencast become a more regular thing then I’ll invest in a better microphone. Until then, this will do.

Happy hackin’!

Tags: obs, screencasts, recording, about.
Categories: Software, Blablabla.

Docker nginx host not found in upstream error

published on January 30, 2018.

I’ve been toying around with Docker for the past couple of days, mostly to learn more about it, to understand it better. I just didn’t bother with it until now.

I started from scratch. Installing Docker, configuring it (I really don’t appreciate it filling my root partition with images), and, well, using it. I sort of figured out the docker command line interface, I get the difference between images and containers, I know how to write a Dockerfile, and when all the commands and options and flags start get confusing I know where to look in the help for help.

Happy with the progress I made, it was time to start connecting different containers so that they can talk to each other. Starting with a single container with nginx in it, and another container with php-fpm in it. Using their official images even.

To keep my sanity intact, as much as it is possible with software these days, I heeded Vranac’s advice and installed docker-compose for that.

No cheating, so I wrote my own docker-compose.yml file using just the documentation:

version: '3'

        image: php:7.2-fpm
            - "9000"
            - ./app:/app

        image: nginx:stable
            - "8080:80"
            - ./site.conf:/etc/nginx/conf.d/default.conf
            - ./app:/app
            - php

And now let’s build it and bring up the containers:

$ docker-compose build
$ docker-compose up

Aaaaaaand… It dies with an error like:

nginx: [emerg] host not found in upstream "php" in /etc/nginx/conf.d/default.conf:15

Blergh. I guess I missed something from the documentation. Fast-forward 2 hours, dozens of google searches and articles, countless rewrites of the docker-compose.yml file, and zero luck. Whatever I did, same error: “host not found in upstream”.

Then I finally remembered. What is the one thing that always causes me grief when trying to work with a web server? That’s right: SELinux!

Turn off selinux, restart docker, build && up, and it works. Sonofa. Works even with the very first version of docker-compose.yml I wrote.

OK, turning off selinux can’t be the solution, so I searched more… And no one, ever, recommends, or even mentions, that selinux might be the problem. I’ve installed the Docker SELinux package (it’s container-selinux on my Fedora 26). It should be working!

Another hour later, more searches and articles, I end up at the beginning, at the “Get Docker CE for Fedora” documentation page. Docker CE? What the fresh hell is this?

Well, it’s the docker version I should’ve installed in the first place.

Fedora’s repos have docker version 1.13.something. Docker-CE is at 17.12.something.

Remove old docker, re-enable selinux, install new docker, everything works just fine, and run the following:

sudo ausearch -c 'iptables' --raw | audit2allow -M my-iptables
sudo semodule -X 300 -i my-iptables.pp

I have no idea what that does, but it was required to make it work.


Happy hackin’!

Robert Basic

Robert Basic

Software engineer, consultant, open source contributor.

Let's work together!

If you require outsourcing or consulting help on your projects, I'm available!

Robert Basic © 2008 — 2019
Get the feed