Tag Archives: Git

Heroku deploy sub-directory

Going through a couple of Udemy courses, and figured it was nice to keep all the code I wrote while doing them in a single github repository.

Was working nicely until I started the Node with React where part of the course is to deploy the app to Heroku which wants a full repository pushed to a certain git repo it creates for deployment. But in my case the app I want to deploy is of course a sub-directory…

Turns out there’s a git command called subtree one can use here:

# Setup
heroku login
heroku create

git remote add heroku/some-name https://git.heroku.com/{created-heroku-app-id}.git

# Deploy
git subtree push --force --prefix path/to/app heroku/some-name master

The subtree command needs to be run from the top-level directory of the git repository, but one can add a script command to the apps package.json, for example like this:

{
  "scripts": {
    "deploy": "cd ../../.. && git subtree push --prefix path/to/app heroku/some-name master"
  }
}

Unfortunately, subtree push doesn’t support --force, but a workaround for that is running it nested like this:

git push heroku/some-name `git subtree split --prefix path/to/app master`:master --force

Which unfortunately doesn’t work on Windows… but you can do it in two steps instead:

git subtree split --prefix path/to/app master
git push heroku/some-name {id-from-previous-command}:master --force

Stop Git from messing with my newlines

I’m sorry, but I just hate when Git is messing with my files…

warning: CRLF will be replaced by LF in some/file.ext.
The file will have its original line endings in your working directory.

That’s just not its job! If I want to enforce a certain new line regime, there’s linting tools, pre-commit hooks, etc.

The following should stop it, but frankly, sometimes it feels like git just keeps inventing new ways of reverting to its hyper annoying default…

# First run this to see where it's configured now
> git config --list --show-origin

# Then run whichever works...
> git config --global core.autocrlf false
> git config --system core.autocrlf false
> git config --local core.autocrlf false

Using SSH keys with BitBucket/GitHub on Windows

Couldn’t get this to work, but now it does, so… time for another “note to self”. 🙂

Prerequisites

  • Git, obviously…
  • PuTTY, with puttygen, plink and pageant, to be exact…

Setup

  1. Open puttygen.
  2. Load your private key, or generate a new one and save it.
  3. Copy your public key (“Public key for pasting …”) to BitBucket/GitHub/etc.
  4. Open pageant
  5. Load your private key.
  6. Check that the key authentication works by running e.g.
    plink -v git@bitbucket.org
    plink -v git@github.com
  7. Point the GIT_SSH environment variable to plink.exe.

Now, as long as pageant is running with your private key loaded, it should work to clone, pull, push, etc. to/from both private and public repos. E.g. git clone git@github.com:example/some-private-repo.git.

Key here, for me, was the GIT_SSH variable that so many blogs, StackOverflow answers and forum posts failed to mention… Without that set, the plink check did still work, but git clone did not. It just failed with an authentication error. With that variable set it now works perfectly. 🙄🙂👍

Sources: makandracards.com, vladmihalcea.com

Setting up GPG signing for Git/GitHub on Windows

What I did to get from working GPG to green and verified signatures for Git commits and tags on GitHub.

  1. Find the long id of the Signing key we want to use:
    🔶 $ gpg --edit-key alice
    gpg (GnuPG) 2.0.30; Copyright (C) 2015 Free Software Foundation, Inc.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

    Secret key is available.

    pub  4096R/AA79CCAE  created: 2017-08-23  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    sub  4096R/62275E24  created: 2017-08-23  expires: never       usage: S 👈
    sub  4096R/4AEA9524  created: 2017-08-23  expires: never       usage: E
    [ultimate] (1). Alice Person (alice) <alice.person@example.com>
    [ultimate] (2)  Alice Person (alice) <alice@example.org>

    🔶 gpg> quit

    🔶 $ gpg --list-secret-keys --keyid-format LONG alice
    sec   4096R/8C0BBECBAA79CCAE 2017-08-23
    uid                          Alice Person (alice) <alice.person@example.com>
    uid                          Alice Person (alice) <alice@example.org>
    ssb   4096R/6ADB9D4262275E24 2017-08-23 👈
    ssb   4096R/33F2E1644AEA9524 2017-08-23

    Note: So in this case we want 6ADB9D4262275E24

  2. Configure git and (optionally) make it sign all commits by default:
    🔷 $ git config --global user.name "Alice Person"
    🔷 $ git config --global user.email "alice.person@example.com"
    🔶 $ git config --global user.signingkey "6ADB9D4262275E24"
    🔷 $ git config --global commit.gpgsign true
    🔷 $ git config --global push.gpgsign if-asked
    🔶 $ where gpg
    C:\Program Files (x86)\GNU\GnuPG\pub\gpg.exe
    🔶 $ git config --global gpg.program "C:/Program Files (x86)/GNU/GnuPG/pub/gpg.exe"

    Note: If repo specific, just skip --global and run the command in the repo instead.

Test it…

  1. Do a commit:
    🔷 $ git init gpg-test
    🔷 $ cd gpg-test
    🔷 $ touch file.txt
    🔶 $ git commit -a -m "Signed commit"

    You need a passphrase to unlock the secret key for
    user: "Alice Person (alice) <alice.person@example.com>"
    4096-bit RSA key, ID 62275E24, created 2017-08-23 (main key ID AA79CCAE)

    [master (root-commit) 2814856] Works...?
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 file.txt

    Note: One can also use the the -S option as alternative to using the commit.gpgsign true config, but as a forgetful person, I’d advice against that… Either set the config globally, or for the specific repo you need it for.

  2. Verify commit was signed:
    🔷 $ git log --show-signature
    commit 2814856365a07b3deb374f1337258102c06b77ef
    gpg: Signature made 08/23/17 06:18:50 W. Europe Daylight Time^M
    gpg:                using RSA key 6ADB9D4262275E24^M
    gpg: Good signature from "Alice Person (alice) <alice.person@example.com>" [ultimate]^M
    gpg:                 aka "Alice Person (alice) <alice@example.org>" [ultimate]^M
    Author: Alice Person <alice.person@example.com>
    Date:   Wed Aug 23 06:18:48 2017 +0200

        Signed commit
  3. Add a signed tag, using -s:
    🔶 $ git tag -s v1 -m "Signed tag"

    You need a passphrase to unlock the secret key for
    user: "Alice Person (alice) <alice.person@example.com>"
    4096-bit RSA key, ID 62275E24, created 2017-08-23 (main key ID AA79CCAE)

    Note: Unfortunately, unlike for commits, there is no tag.gpgsign true config as of writing, so to sign tags the -s option has to be remembered.

  4. Verify tag was signed:
    🔷 $ git tag -v v1
    gpg: Signature made 08/23/17 06:34:18 W. Europe Daylight Time
    gpg:                using RSA key 6ADB9D4262275E24
    gpg: Good signature from "Alice Person (alice) <alice.person@example.com>" [ultimate]
    gpg:                 aka "Alice Person (alice) <alice@example.org>" [ultimate]
    object 53e7f2e637eaf3c47b5dcad30b57be7b6829be02
    type commit
    tag v1
    tagger Alice Person <alice.person@example.com> 1503462856 +0200

    Signed tag

Add GPG key to GitHub

  1. Export the public key:
    🔶 $ gpg -a --export alice > public.txt
  2. Copy it.
  3. Go to GPG keys on GitHub.
  4. New GPG Key.
  5. Paste it.
  6. Add GPG Key.
  7. Pushed commits and tags should now look verified, as in this post: GPG signature verification

Sources: help.github.com, StackOverflow, git-scm.com

Edit composer dependencies “inline” while developing

Have a PHP project, and want to re-use some classes in a new project. Moving them to their own repository and turning them into a Composer dependency is a clean way to do that. If hosted on GitHub/BitBucket, it’s even simply to be a bit more proper and fancy by publishing the package on Packagist with automatic updates based on git tags. However, if still heavily developing both the project and the dependency, the round trip through repo/packagist is a pain.

But today I discovered there’s an option called --prefer-source which seems to solve most of this pain. And here’s a basic note-to-self on how to get that to work…

0. Make sure dependency is a composer dependency

// Dependency composer.json
{
    "name": "my/package",
    "autoload":
    {
        "psr-4": {"": "src/"}
    }
}

1. Add dependency repo and package to root project

// Root project composer.json
{
    "repositories":
    [
        {"type": "vcs", "url": "https://github.com/username/my-project"}
    ],
    "require":
    {
        "my/project": "dev-master",
    }

2. Run update with –prefer-source

$ composer require my/package dev-master --prefer-source

We should now have the package downloaded and, more importantly, if you check ./vendor/my/package it should have the .git directory, meaning you can make immediately working changes there directly, and commit when you’re happy… Our other root project(s) depending on it should then get the update from the source repository after an easy composer update. 👍


Note: I’m a bit fuzzy on what composer does to keep track on whatever different happens through --prefer-source, and it’s an option for both composer install and composer update. For example, at first attempt, I tried to use composer update --prefer-source on a dependency that had already been downloaded, and the .git directory did not turn up, but if I just deleted the vendor directory for that package and then re-ran the command, then the .git was there.

So, feel free to comment if you have some light on that topic 😛🤓