git

Git 2.20.1 is super slow on macOS Mojave on my work Mac

Update: I just upgraded my personal mac to 2.20.1, and am experiencing none of the slowdown I had on my work Mac. So something else is afoot. Maybe some of the 'spyware-ish' software that's installed on the work mark is making calls like lstat() super slow? Looks like I might be profiling some things on that machine anyways :)

I regularly use Homebrew to switch to more recent versions of CLI utilities and other packages I use in my day-to-day software and infrastructure development. In the past, it was necessary to use Homebrew to get a much newer version of Git than was available at the time on macOS. But as Apple's evolved macOS, they've done a pretty good job of keeping the system versions relatively up-to-date, and unless you need bleeding edge features, the version of Git that's installed on macOS Mojave (2.17.x) is probably adequate for now.

But back to Homebrew—recently I ran brew upgrade to upgrade a bunch of packages, and it happened to upgrade Git to 2.20.1.

Git gives 'ERROR: Repository not found.' when URL is correct and SSH key is used

I had a fun problem that made me spin my wheels an hour or so today. I was having no issue cloning a remote repository a number of times in the morning while debugging a Jenkins build job that runs a git clone + Docker image build and push operation.

Suddenly, when I was doing some final testing, I started to get the following:

git clone [email protected]:geerlingguy/my-project.git                            
Cloning into 'my-project'...
ERROR: Repository not found.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

I know that I had the repository's SSH key loaded (via eval "$(ssh-agent -s)" && ssh-add ~/.ssh/deploy-key), and if I unloaded the key, I would instead get:

Cloning private GitHub repositories with Ansible on a remote server through SSH

One of Ansible's strengths is the fact that its 'agentless' architecture uses SSH for control of remote servers. And one classic problem in remote Git administration is authentication; if you're cloning a private Git repository that requires authentication, how can you do this while also protecting your own private SSH key (by not copying it to the remote server)?

As an example, here's a task that clones a private repository to a particular folder:

- name: Clone a private repository into /opt.
  git:
    repo: [email protected]:geerlingguy/private-repo.git
    version: master
    dest: /opt/private-repo
    accept_hostkey: yes
  # ssh-agent doesn't allow key to pass through remote sudo commands.
  become: no

If you run this task, you'll probably end up with something like:

SVN2Git and "fatal: bad default revision 'HEAD'"

I was recently converting a repository from SVN to Git using KDE's SVN2Git, and after the conversion was done, the repository didn't seem to work that well. Inside the bare repo, if I tried git log, I received:

fatal: bad default revision 'HEAD'

I also tried git fsck, which resulted in:

notice: HEAD points to an unborn branch (master)

After trying a few different methods to resurrect the git repository, I noticed that my SVN2Git rules file defined the name of the resulting git repository as example-example (note the dash). Removing the dash fixed the issue, and now I have a happy git repository!

tl;dr: Don't use special characters in the name of the resulting git repository in SVN2Git's rules file.

Switching an SVN repository to Git using git svn

Converting from an SVN repository to a Git repository is fairly simple—you just want to move all the commits across, preserve your tags and branches, and make sure all the commit authorship translates properly. The simplest method (though not always fastest) is to use the git svn command to do the full conversion. (Note also that you could interact with an SVN repository with Git as the middle man using git svn... but this blog post is just about doing a full conversion).

Converting the authors

Before you convert the SVN repository to Git, you need to get a list of all the SVN commit authors, and then set up the list for git svn to be able to translate SVN commit authors to Git commit authors (the Git format is slightly different, using a name + email combination). First, in a terminal window, run the following command within a local checkout of the SVN repository:

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors.txt

Simple Git-based multi-server deployments

Ansible is used to manage most of Midwestern Mac's infrastructure and deployments, and while it's extremely easy to use, there are a couple situations where a project just needs a little code to be updated across two or more servers, from a central Git repository, or from one master application server.

All Git repositories include a hooks folder, which contains sample git hook scripts. Inside this folder are a series of sample hook files like post-commit.sample and pre-rebase.sample. If you add a shell script of the same name as any of these files (excluding the .sample) to this folder, Git will run the script when the particular action runs (e.g. git will run a post-commit script after a commit).

Switching an SVN repository to Git with KDE's Svn2Git

Some places where I've worked have used SVN for version control, and while the supposed simplicity and centralization of SVN can be nice in certain situations, SVN can't hold a torch to Git's speed, flexibility, and ubiquity (nowadays) for source control. Not to mention SVN doesn't have real tags or branches, just quasi-directories that can easily be mangled into a horrific mess (I see this quite often).

I've had to use some incredibly large (10,000+ revisions, 2GB+ total size) SVN repositories, and while I've managed them using git svn sometimes (see Switching an SVN repository to Git using git svn), it's much nicer to be able to migrate the entire team from SVN to Git so everyone can work on the repository much more efficiently.

Remove Tower's .git folder association in Mac OS X's Finder

I use Tower from time to time to do some git operations that require a little more attention or a better visual overview than what I can get via the CLI and built-in tools. However, I noticed that Tower likes to take over any folder with .git, and make Mac OS X's finder turn it into a 'Tower' package, so double-clicking the folder (which now behaves like a mini app or file) opens Tower.

I don't like that behavior, because I have some [example].git folders that I want to browse in the Finder or in other Mac apps without having to 'Show Package Contents'. Apparently GitX has the same issue, and I'm not the only one annoyed by this behavior.

The fix, for me, was simple:

Stop letting .DS_Store slow you down

I have over 100 git repositories on my Mac, and for almost every one, I sometimes browse the directory structure in the Finder. Once I do that, I inevitably end up with a few pesky .DS_Store files that want to be added to my repo:

Pesky .DS_Store Files in Terminal during Git Status

.DS_Store files don't add anything of value to my code (they just tell Mac OS X about folder display and icons), so I always end up adding them to my own projects' .gitignore files. But when I'm working on other repositories (like Drupal, or a fork from GitHub) I don't want to add a .gitignore if none exists, or mess with the project's existing .gitignore. So what's a coder to do?

There are a couple good solutions: