Saturday, April 24, 2021

How do we get the "diff" or the patch for the very first commit in Git?

This is a summary of several Stack Overflow discusses about how to get the "diff" or the patch for the very first commit in Git.

  1. To get the diff from the very first commit to the empty tree, we can use the following command.
    git diff \
        4b825dc642cb6eb9a060e54bf8d69288fbee4904 \
        $(git log --reverse | head -1 | cut -d' ' -f2)
      
    where 4b825dc642cb6eb9a060e54bf8d69288fbee4904 is the SHA of the empty tree and $(git log --reverse | head -1 | cut -d' ' -f2) retrieves the SHA of the very first commit. Alternatively, we can rewrite the above in a way that perhaps is easier to read.
  2. To get the diff from the very first commit to the empty tree, we can use the following command.
    git diff \
        $(printf '' | git hash-object -t tree --stdin) \
        $(git log --reverse | head -1 | cut -d' ' -f2)
      
  3. To get the patch from the very first commit to the empty tree, we can use the following command.
    git format-patch \
        --root --stdout \
        $(git log --reverse | head -1 | cut -d' ' -f2)
        

Reference 

  1. How to get Git diff of the first commit?  
  2. How to use git format-patch on initial commit

Monday, April 5, 2021

Accessing a SSH host via a SSH gateway?

I wrote the notes about how to synchronize two SSH hosts via a middle SSH gateway and how to access a SSH host via a SSH gateway. The assumption there is to use ssh in OpenSSH. But what if we want to do the same with PuTTY? I actually locate the answer on Stack Overflow. This post is just a bookmark to the answer.

Simply put, it is to use PuTTY's proxy setup on the user interface when we create a session for a host, and the proxy command follows the following format,


plink.exe %user@%proxyhost -P %proxyport -nc %host:%port

or


plink.exe %user@%proxyhost -pw %pass -P %proxyport -nc %host:%port

Note the two comments.

  1. plink.exe is part of the PuTTY suite.
  2. The second plink.exe example is to use the password authentication. Since the password is part of the command line, someone can reveal the password by showing the process command line arguments, such as, using the methods in the notes written here. So use it with caution.

Sunday, April 4, 2021

Synchronizing files on two SSH hosts with one in the middle (accessing a SSH host via a SSH gateway?)

I believe that this is a rather common situation -- I want to copy files from one SSH host to the other; however, the SSH host I want to copy files from or copy files to is behind a SSH gateway. To describe the situation clearly, let's consider three SSH hosts, H, M, and O. I can log on to H via SSH, from H log on M via SSH, but from H not log on to O via SSH. To get to O, I have to log on to M first, and so M is a SSH gateway. In fact, this is a typical setup for many computational cluster, to access the cluster, you SSH to a SSH gateway. How do we copy files between H and O? Of course, we can always copy files from O to M, and M to H, which is somewhat inconvenient. Can we do better? Yes, via SSH's ProxyCommand option. Below we present two two scenarios.

1. SSH to O via M from H

Below is how we get to O "directly" from H assuming the username on M is alice_on_m and that on O alice_on_o.


ssh -o 'ProxyCommand ssh alice_on_m@M -W %h:%p' alice_on_o@O

Note that although we issue this command on H, H does not have to be able to resolve O; however, M must know O.

If you prefer the public key authentication to the password authentication, do the following instead,


ssh -o \
  'ProxyCommand ssh -i ~/.ssh/private_key_for_m alice_on_m@M -W %h:%p' \
  -i ~/.ssh/pri
  vate_key_for_o alice_on_o@O

where we assume that private_key_for_m and private_key_for_o are two private keys on host H, and their respective public keys are in ~alice_on_m/.ssh/authorized_keys at M and ~alice_on_o/.ssh/authorized_keys at O.

To me,  the most convenient method is to set up ~/.ssh/config file on H, with which, we will save some typing on the command line. Below is an example for the ~/.ssh/config file where we add two entries, one for M, and the other for O.

Host M
    HostName M
    ServerAliveInterval 240
    User alice_on_m
    AddKeysToAgent yes
    IdentityFile ~/.ssh/private_key_for_m

Host O
    HostName O
    ServerAliveInterval 240
    User alice_on_o
    AddKeysToAgent yes
    ProxyCommand ssh alice_on_m@M -W %h:%p
    IdentityFile ~/.ssh/private_key_for_o

Once we set up this, we can get on O from H (via M) by simply issing the following command on H,

ssh alice_on_o@O

2. Copying Files from O to H via M using rsync

Assuming we set up ~/.ssh/config correctly, to copy files from O to H via M using rsync, we simply issue a command like the following,


rsync -avzr alice_on_o@O:./foo/ ./foo/

which copies the directory recursively ~alice_on_o/foo at host O to ./foo at host H. Here we also rely on rsync's ability to use SSH as the transport protocol transparently.

Is this neat?