· 5 min read Posted by Kevin Galligan

Part 5: Pulling Changes

GitPortal for KMP - Bidirectional

After KMP code changes are made within app code, they need to eventually be pulled into the other app. GitPortal provides a simple command to accomplish this: pull merge.

As app developers make changes to each of the apps, the KMP changes eventually need to be merged between them. GitPortal provides a few commands to accomplish this:

  • bidir.push
  • bidir.compare
  • bidir.pullmerge
  • bidir.pullmergeresolve

Push

The bidir.push command will grab all commits from the app’s history that impact your KMP module, in our template example that is the library folder, and “recreate” them in the KMP repo.

You’ve already used this command indirectly. The CI process runs this when you have KMP changes in the app repo. We’re explaining it here, but you should never need to run it directly.

The changes are not pushed directly to the tracking branch. Instead, they are pushed to a parallel branch specific to the app they were pushed from. In our case, gitportal/bidir/main-android for Android and gitportal/bidir/main-ios for iOS.

As you merge and push changes to main in your app’s repos, you’ll see changes to the KMP code being pushed into those branches automatically by CI.

If you made the DatabaseHelper change from the previous post in the series, you should see a commit with that change in gitportal/bidir/main-android.

Compare

As changes are pushed from the apps, they are added to the parallel branches listed above. When it’s time to pull changes into the “other” app, you can get a list of the changes to be pulled. This is what bidir.compare does.

For example, to see the DatabaseHelper, open a terminal in the iOS app folder and run the following:

gitportal bidir.compare -c android

You should see that commit listed. The -c android argument tells GitPortal what app we want to compare to. Since we’re in iOS currently, we want to see available commits from Android.

Pull Merge

The bidir.pullmerge grabs the outstanding changes and pulls them into the local app repo. For example, to pull changes into the iOS app, run:

gitportal bidir.pullmerge -c android

Assuming there are no conflicts, you will see a success message. If you run git log, you’ll see a single commit with any changes pulled from Android.

Running bidir.compare again will tell you that there are no outstanding changes.

What actually happens?

In the KMP repo, GitPortal maintains the parallel branches mentioned above. When bidir.pullmerge runs, GitPortal actually runs a git merge operation. Say we’re running from the iOS app, GitPortal will create a merge from gitportal/bidir/main-android into gitportal/bidir/main-ios. In the local app repo, those updates are pulled and commited.

Technically, the changes are not yet merged into gitportal/bidir/main-ios. A merge commit is created, but gitportal/bidir/main-ios is not updated until those changes are commited to iOS main, pushed, and GitPortal’s CI is run again. At this point, it’ll finalize updating gitportal/bidir/main-ios.

Implement and Test

Once KMP changes are pulled, you’ll need to implement and test the app-specific parts of those changes. In our case, there’s not much you need to do (we only added a comment). In a more complex example, iOS screens may need to be created, iOS-specific changes applied, as well as testing on iOS to ensure the KMP changes work as expected.

Once that iOS-side work is done, you commit, push, and PR just like any other iOS change. When those changes are merged, GitPortal’s CI process will finalize the KMP library’s updates.

Pull Merge Conflicts

Because changes are happening in both repos independently, conflicts can occur. When you run bidir.pullmerge, if the git merge operation fails because of a conflict, you need to do what you’d normally do: resolve the merge conflicts.

GitPortal actually creates a git worktree in which it runs bidir.pullmerge. If the merge fails, you’ll be directed to that worktree folder to resolve the merge conflicts.

What is a git worktree?

Normally when working with different git branches, you’d checkout (or “switch”) to a different branch. While this is generally file, it forces you to resolve uncommitted local changes, and can disrupt whatever you were currently focused on.

Another alternative is a git worktree. It’s another folder where git will checkout a different branch from the same repo. You can work in this folder, without disrupting your work in the original folder.

They can actually be useful for your regular workflow. I’m currently editing this tutorial in a worktree because we have a whole bunch of other docs being edited in a different branch.

Read More

The merge worktree folder is just a regular git branch. You can use whatever method or tools you normally would to resolve the merge conflicts. Once resolved, commit them locally (don’t try to push. You won’t break anything, but you’ll have extra branches in your KMP repo).

Personally, I use Intellij to resolve merge conflicts in my day-to-day code editing. To do that, you can simply open the worktree folder with Intellij.

Local Config

The GitPortal CLI tool supports adding a default tool to open when there are merge conflicts.

There are two “officially” supported options, Intellij IDEA and Android Studio, but you can supply your own command if you’d like to use something else.

To have Intellij IDEA open automatically for merge conflicts, run:

gitportal localconfig -proc idea

Most tools will just take the worktree path as an argument, but some tools have their own command line param format. To use an arbitrary command, run the following:

gitportal localconfig -cmd 'sometool {dir}'

The {dir} will be replaced with the path to the worktree. Some tools are picky about paths, so you may need to tweak arbitrary command strings (a “test” of this command setting is on the roadmap).

Pull Merge Resolve

When the merge conflicts are resolved, add and commit them to the worktree branch.

Now, you’ll need to run bidir.pullmergeresolve. This will “complete” the pull merge step.

When a pull merge has no conflicts, the complete step is performed automatically. When there are conflicts, you need to run the complete step manually after resolving conflicts.

Make sure to open a terminal in the main repo directory. Not in the worktree folder. Then run:

gitportal bidir.pullmergeresolve

Assuming success, you’re done!

Well, sort of. Again, you need to go through your normal PR and merge process for the app, as with the no-conflict bidir.pullmerge example above.

If successful, the bidir.pullmergeresolve command will delete the worktree folder. It’s best to make sure you’ve closed whatever window or terminal was accessing that folder.