Tutorial

Here, you'll find a quick overview over the most common functionality of GRM.

Managing existing repositories

Let's say you have your git repositories at ~/code. To start managing them via GRM, first create a configuration:

grm repos find local ~/code --format yaml > ~/code/config.yml

The result may look something like this:

---
trees:
  - root: ~/code
    repos:
      - name: git-repo-manager
        worktree_setup: true
        remotes:
          - name: origin
            url: "https://github.com/hakoerber/git-repo-manager.git"
            type: https

To apply the configuration and check whether all repositories are in sync, run the following:

$ grm repos sync config --config ~/code/config.yml
[✔] git-repo-manager: OK

Well, obiously there are no changes. To check how changes would be applied, let's change the name of the remote (currently origin):

$ sed -i 's/name: origin/name: github/' ~/code/config.yml
$ grm repos sync config --config ~/code/config.yml
[⚙] git-repo-manager: Setting up new remote "github" to "https://github.com/hakoerber/git-repo-manager.git"
[⚙] git-repo-manager: Deleting remote "origin"
[✔] git-repo-manager: OK

GRM replaced the origin remote with github.

The configuration (~/code/config.yml in this example) would usually be something you'd track in git or synchronize between machines via some other means. Then, on every machine, all your repositories are a single grm repos sync away!

Getting repositories from a forge

Let's say you have a bunch of repositories on GitHub and you'd like to clone them all to your local machine.

To authenticate, you'll need to get a personal access token, as described in the forge documentation. Let's assume you put your token into ~/.github_token (please don't if you're doing this "for real"!)

Let's first see what kind of repos we can find:

$ grm repos sync remote --provider github --token-command "cat ~/.github_token" --root ~/code/github.com/ --format yaml
---
trees: []
$

Ummm, ok? No repos? This is because you have to tell GRM what to look for (if you don't, GRM will just relax, as it's lazy).

There are different filters (see the forge documentation for more info). In our case, we'll just use the --owner filter to get all repos that belong to us:

$ grm repos find remote --provider github --token-command "cat ~/.github_token" --root ~/code/github.com/ --format yaml
---
trees:
  - root: ~/code/github.com
    repos:
      - name: git-repo-manager
        worktree_setup: false
        remotes:
          - name: origin
            url: "https://github.com/hakoerber/git-repo-manager.git"
            type: https

Nice! The format is the same as we got from grm repos find local above. So if we wanted, we could save this file and use it with grm repos sync config as above. But there is an even easier way: We can directly clone the repositories!

$ grm repos sync remote --provider github --token-command "cat ~/.github_token" --root ~/code/github.com/
[⚙] Cloning into "~/code/github.com/git-repo-manager" from "https://github.com/hakoerber/git-repo-manager.git"
[✔] git-repo-manager: Repository successfully cloned
[✔] git-repo-manager: OK

Nice! Just to make sure, let's run the same command again:

$ grm repos sync remote --provider github --token-command "cat ~/.github_token" --root ~/code/github.com/
[✔] git-repo-manager: OK

GRM saw that the repository is already there and did nothing (remember, it's lazy).

Using worktrees

Worktrees are something that make it easier to work with multiple branches at the same time in a repository. Let's say we wanted to hack on the codebase of GRM:

$ cd ~/code/github.com/git-repo-manager
$ ls
.gitignore
Cargo.toml
...

Well, this is just a normal git repository. But let's try worktrees! First, we have to convert the existing repository to use the special worktree setup. For all worktree operations, we will use grm worktree (or grm wt for short):

$ grm wt convert
[✔] Conversion done
$ ls
$

So, the code is gone? Not really, there is just no active worktree right now. So let's add one for master:

$ grm wt add master --track origin/master
[✔] Conversion done
$ ls
master
$ (cd ./master && git status)
On branch master
nothing to commit, working tree clean

Now, a single worktree is kind of pointless (if we only have one, we could also just use the normal setup, without worktrees). So let's another one for develop:

$ grm wt add develop --track origin/develop
[✔] Conversion done
$ ls
develop
master
$ (cd ./develop && git status)
On branch develop
nothing to commit, working tree clean

What's the point? The cool thing is that we can now start working in the develop worktree, without affecting the master worktree at all. If you're working on develop and want to quickly see what a certain file looks like in master, just look inside ./master, it's all there!

This becomes especially interesting when you have many feature branches and are working on multiple features at the same time.

There are a lot of options that influence how worktrees are handled. Maybe you want to automatically track origin/master when you add a worktree called master? Maybe you want your feature branches to have a prefix, so when you're working on the feature1 worktree, the remote branch will be origin/awesomefeatures/feature1? Check out the chapter on worktrees for all the things that are possible.