GitPortal

GitPortal - Git Repo Source-Linking Tool

GitPortal is a command-line tool that syncs source code across git repos. It is designed to specifically support sharing code with Kotlin Multiplatform.

GitPortal is in Alpha

GitPortal is undergoing development. Changes should be mostly adding features. The docs will note features more likely to change.

What does GitPortal do?

GitPortal can pull a remote repo’s content into a folder in your local repo. It is conceptually similar to git submodule and git subtree, although the specific details of how it tracks linked repos and it’s commands are geared towards a more specific goal.

GitPortal’s internals are based on git subrepo. Git subrepo is an alternative to the other two “official” options, written to compensate for issues with both. GitPortal has been rewritten from the ground up to better support ongoing development and add several missing features, but many of the basic concepts are the same.

Internally, GitPortal uses standard git operations to analyze and move code between repos.

Operating Modes

There are two basic operations modes: Unidirectional and Bidirectional. These model library publishing and feature development workflows, respectively.

For a more extensive background on what these modes do and why they exist, please see KMP For Native Mobile Teams.

Unidirectional (AKA Library Publishing)

In this mode, GitPortal pulls code from the KMP repo into an app repo. The concept is that this is like publishing dependencies, except with code.

Why not binaries and KMMBridge?

It depends on your goals. If you just want to share some KMP code that other team members can use, KMMBridge is fine. We’ve recently updated it to be even simpler to set up and use.

However, if your goal is to start using KMP at scale and get the whole team involved, binaries are a waste of time. With KMP, the iOS developers have a harder time. They have more to learn, and the developer experience is significantly worse.

For published dependencies in particular, while Android devs can browse and debug JVM dependencies because of source jars, iOS developers cannot do the same with binary XCFrameworks. The iOS team essentially gets a black box. We feel that, far from a positive introduction to KMP, this reinforces the perception that KMP will be an “Android thing”, and certainly does nothing to move the iOS team towards learning KMP or getting involved.

In addition, few Android devs who are KMP beginners understand how to build KMP APIs that look good from Swift. So, the result is a black box, with an ugly API.

Bidirectional

Bidirectional is fairly unique and more detail is needed to explain how it works.

Essentially, for teams using KMP inside their separate native mobile apps, the idea is that these teams can edit their apps independently as they do now. App-specific code as well as shared KMP code. Edits to either side are only concerned with the functionality and features of that app.

If an edit has KMP changes, GitPortal (likely through CI) will push that change to the KMP repo.

A developer from the “other” app can review and pull those changes in, on their schedule, then test, edit, and commit them to the app itself.

The shared KMP maintains “eventual consistency”. The teams aren’t forced into a coupled workflow, as would be the case if all of the code, apps and KMP, was merged into a single repo.

Bidirectional Constraints

The bidirectional mode has significant constraints currently. It will sync on one target branch only, usually main (master, trunk, whatever). You choose that when setting up the links. It also can only pull a linear history. No cherry-picking features across repos, etc.

These constraints were put in as trying to support every imaginable feature would be rather difficult, and not very useful. We are working with teams to get feedback and discover what they actually need and find valuable, and adding those features incrementally. For example, plans for multiple branches are in the works, as is an Intellij plugin to make review and management simpler.

If you are interested in using these features as they are available, please reach out.

Installation

MacOS

On MacOS, you can install GitPortal through Homebrew.

brew tap touchlab/homebrew-gitportal
brew install gitportal

The current version of GitPortal is 0.7.22

Other Platforms

We are working through other platform releases, but currently homebrew for mac is the only public install option. Reach out if you need another platform.

Operation

We have two tutorials for GitPortal available: one for Unidirectional and one for Bidirectional. Please see those for detailed introductions to GitPortal and it’s usage.

Commands

The commands included with GitPortal are the following:

Usage: gitportal options_list
Subcommands: 
    setup - Setup KMP Module Unidirectional
    check - Check if KMP module has changes
    pull - Pull upated code
    push - Push updated code
    create - Create GitPortal module from existing code
    bidir.setup - Setup KMP Module Bidirectional
    bidir.check - Check if KMP module has changes against bidirectional remote
    bidir.push - Push updated code
    bidir.create - Create GitPortal module from existing code
    bidir.compare - Compare my history with app history
    bidir.pullmerge - Pull merge of other app
    bidir.pullmergeresolve - Commit pull merge conflict resolve
    bidir.rebaselibrary - Rebase library remote branch
    localconfig - Set local user config
    status - GitPortal module status
    autoci - For CI. Check for unidirectional, push for bidirectional
    deploykey - Create Deploy Key and secrets

Options: 
    --version, -v [false] -> Print GitPortal version 
    --help, -h -> Usage info 

Some quick highlights from that list. Everything with a bidir prefix are specific to the bidirectional mode. setup, check, pull, push, and create are specific to the unidirectional mode.

Most of those commands would be rarely, or never called by most users, with and admin and CI doing the config and day-to-day work.

localconfig allows each user to config GitPortal. Currently this allows you to specify the application to open for merge issues with bidir.pullmerge.

autoci is just for CI. It’ll determine if your module is unidirectional or bidirectional, then act accordingly.

deploykey is described in the tutorials. It is specific to GitHub. Essentially, it’ll configure the different repos to talk to each other from GitHub Actions CI. Doing so manually is best avoided if possible.