Tagged: git

Git: Subtree tutorial

Git submodules are a pain to deal with. Git subtrees are much nicer.

Let’s start with your parent repo, and another repo, currently completely separate. The latter of these will be the subtree repo.

1) Let’s add the repo like a normal repo: git remote add my-subtree git@github.com:your_username/your_repo.git.

2) Add the other repo as a subtree: git subtree add --prefix=the_folder/ my-subtree master.

That is, git subtree add and then the name of the folder it will live in and finally the repo name and branch.

3) Make a change to the files in the_folder and commit. Your parent repo, along with the files in the subtree, will be updated. But the subtree will not.

When you want update the files in the subtree repo run git subtree push --prefix=the_folder my-subtree master. And the same command but with pull to pull any new changes.

There are more things to learn, like whether you could squash commits and how all this relates to rebasing, but that’s the basics.


Git: Alias for multiple Github accounts in SSH

Say you have two github accounts. So you have different SSH keys. Github won’t know which key relates to which account.

However, in your ~/.ssh/config file you can setup an alias that uses the correct IndentityFile to send to github.

In that file, put this:

Host new_alias
        Hostname github.com
        User git
        IdentityFile ~/.ssh/id_rsa_new_identity

Now you can use git remote origin git@new_alias:your_username/therepo.git Note the : after the alias name. And the fact you’re putting git@ at the start.


HockeyApp: Generating release notes from git

The problem with uploading to HockeyApp is the release notes are not automatically created.

And we can create them by looking at all the git commit logs since the last build.

For this to happen we need to know what the last commit was.

Although we can specify this in our upload, when we query the builds we can’t get this information back. Instead, we’ll add the commit SHA to the release notess.

Our plan will be

  1. Look at the app versions via HockeyApp’s API
  2. Find the lastest version
  3. Look at the release notes that and retrieve our added commit SHA
  4. Make git output all our commit logs since then
  5. Make release notes out of that (including the current git commit)

Here’s the entire commented shell script:

# We need an initial bullet point for our list of commit logs
echo -n "* "
# Get the latest app uploads
curl -H "X-HockeyAppToken: $HOCKEYAPP_TOKEN" \
"https://rink.hockeyapp.net/api/2/apps/YOUR_HOCKEYAPP_APP_ID/app_versions?page=1" | \
# Put every property on a separate line
sed 's/,/\n/g' | \
# Remove all the quotation marks
sed 's/"//g' | \
# Look at only the notes properties
grep notes | \
# Look at the first one, i.e. the latest app upload
head -n 1 | \
# Find the commit information at the bottom of the notes
sed -n 's/.*(commit:\([^)]*\)).*/\1/p' | \
# Let's find all the logs since that commit
xargs -I '{}' git log {}..HEAD --pretty=format:'%s' --no-merges | \
# Add a star to each newline to make the list
sed ':a;N;$!ba;s/\n/\n* /g'
# The end of the revision log must have the latest commit
# This is so later we can do the above again
echo -n "* (commit:" 
git rev-parse HEAD | xargs echo -n
echo -n ')'

And when we upload to HockeyApp, via travis-ci, we can include it like so:

- bash release_notes_for_hockeyapp.sh > release_notes
- >
  -F "status=2"
  -F "notify=1"
  -F "notes=<release_notes"
  -F "notes_type=0"
  -F "ipa=@app/build/outputs/apk/YOUR_APK.apk"
  -H "X-HockeyAppToken: $HOCKEYAPP_TOKEN"
hockeyapp git travis-ci

Git: get the latest commit

This is easy enough git rev-parse HEAD.

git git-lastest-commit-hash

Git: Subtree basics

If you hate git submodule, then you may want to give git subtree a try.

Let’s say you have a git repository init’d with at least one commit.

You can add another repository to this respository like this:

  1. First specify you want to add the subtree
  2. Then specify the prefix directory into which you want to pull
  3. Specify the remote repository
  4. Specify the remote branch
  5. Specify you want to squash all the remote repository’s logs

In other words

git subtree add --prefix .vimrepo https://github.com/newfivefour/vimrc.git master --squash

This will clone https://github.com/newfivefour/vimrc.git into the directory .vimrepo.

If you want to pull in any new commits to the subtree from the remote, issue the same command as above, replacing add for pull:

git subtree pull --prefix .vimrepo https://github.com/newfivefour/vimrc.git master --squash

If you make a change to anything in .vimrepo the commit will be stored in the host repository and its logs.

That is the biggest change from submodules.

If you now want to update the subtree repository with that commit, you must run the came command as above, excluding --squash and replacing pull for push.

git subtree push --prefix .vimrepo https://github.com/newfivefour/vimrc.git master

I’ve only just starting playing, but my main problems so far:

  1. You can’t easily list the subtrees in your project
  2. You can’t, at least easily, list the remote repositories of the subtrees
  3. The logs are slightly confusing when you update the host repository with subtree commits, then push the subtree to its host, and then pull the subtree.

Other than that, they’re looking nicer than submodules.

git git-subtree

Page 1 of 3