Skip to content

Instantly share code, notes, and snippets.

@markusfisch
Last active June 29, 2019 00:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save markusfisch/c50e3f134a32b4026e35 to your computer and use it in GitHub Desktop.
Save markusfisch/c50e3f134a32b4026e35 to your computer and use it in GitHub Desktop.
A lean approach to managing git subtrees manually

Manage subtrees manually

A lean approach to managing git subtrees manually. Because git-subtree clutters the history graph and git-stree still does too much for me.

I wanted the simplest possible solution that does not require anything special and that does not modify a repository beyond what's required for the most basic approach.

So you may use this script to manage a subtree. But your repository won't depend on it.

Samples

Adding a subtree:

$ git sub add https://github.com/you/component.git

This clones the repository "component" into the directory "component". The directory is now in the staging area and ready to be committed. git-sub won't make any commits.

Later, when you want to update the "component" subtree do:

$ git sub update component

The updated files are now in the staging area and can be committed.

Usage

usage: git sub add    <repository> <prefix>
   or: git sub update <remote>

Use the optional prefix argument to put the repository into a subfolder. By default, repositories are put into the parent repository's root folder.

Cloning

Remotes don't get cloned. So you can't run

$ git sub update component

on a fresh copy. Instead, if you want to add or update a component with one command only use

$ git sub add https://github.com/you/component.git

because add also updates a component if it's already a remote.

Installation

Just put git-sub somewhere in your path and make it executable.

#!/usr/bin/env bash
# Update subtree from remote name
#
# @param 1 - name of remote
update()
{
[ "$1" ] || return $?
git fetch --no-tags "$1" &&
git merge -s subtree --squash "$1/master"
}
# Add (or update) a subtree from a repository URL
#
# @param 1 - URL of repository
# @param 2 - prefix for repository directory (optional)
add()
{
local NAME=${1##*/}
NAME=${NAME%.*}
[ "$NAME" ] || return $?
if git remote | fgrep "$NAME" &>/dev/null
then
update "$NAME"
else
git remote add "$NAME" "$1" &&
git fetch --no-tags "$NAME" &&
git read-tree --prefix="$2$NAME/" -u "$NAME/master"
fi
}
# Print help
help()
{
cat <<EOF
usage: git sub add <repository> <prefix>
or: git sub update <remote>
EOF
}
if [ "$0" == "${BASH_SOURCE[0]}" ]
then
"${@:-help}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment