Skip to content

Using Git 'Local' Remote

Issue

The goal is, keeping commits clean on the branch in GitLab.
I have several local projects that use the same remote repository as a submodule.
The current directory tree for c++ projects is like this:

c++src/
├── qt-concepts
│   ├── bin
│   ├── cmake
│   │   ├── cpack
│   │   └── lib (submodule)
│   ├── cmake-build
│   ├── concept
│   ├── doc
│   ├── lib
│   └── src
├── qt-tts-piper
│   ├── bin
│   ├── cmake
│   │   ├── cpack
│   │   └── lib (submodule)
│   ├── cmake-build
│   ├── doc
│   ├── download
│   ├── lib
│   └── src
└── trial-devops
    ├── bin
    ├── cmake
    │   ├── cpack
    │   └── lib (submodule)
    ├── cmake-build
    ├── doc
    ├── lib
    └── src

The three projects all share the same remote repository as a submodule (cmake/lib). Where as the trial-devops project is the test project for submodule.

When working on the individual projects, the common submodule (cmake-lib) can get regular small messy changes.

Solution

Setup Local Remote

To keep the commit history clean, a local remote is used. It sounds weird, but it works. To share modifications between local projects a remote named lead is set up besides origin which is the GitLab server upstream remote.

To add the local remote lead (lead project) as a relative path to the submodule:

git -C cmake/lib remote add lead ../../../trial-devops/cmake/lib
# Check it out.
git -C cmake/lib remote -v

The result:

lead    ../../../trial-devops/cmake/lib (fetch)
lead    ../../../trial-devops/cmake/lib (push)
origin  https://git.scanframe.com/library/cmake-lib.git (fetch)
origin  https://git.scanframe.com/library/cmake-lib.git (push)

The non-lead projects' submodule points to the lead project's one therefore the remote origin is actually obsolete.

Create a local branch using lead/dev-hotfix as the upstream:

git checkout -b local lead/dev-hotfix

Compare the commit logs of the two branches (should be the same):

# Frist fetch the lead project.
git -C cmake/lib fetch -v lead
# Compare the two branches.
git -C cmake/lib log --oneline --left-right origin/dev-hotfix...lead/dev-hotfix

Local Lead-Project Setup

In the lead project, the submodule auto-updates are enabled by:

git -C cmake/lib config receive.denyCurrentBranch updateInstead

On the lead project uncommitted changes in the active branch are not overwritten. Instead, the push will be rejected if the remote working tree is not clean.

Commiting Clean Changes to GitLab

To clean up the commit history, the lead project squashes the commits before pushing.

git -C cmake/lib rebase --interactive origin/dev-hotfix
# Using a short option.
git -C cmake/lib rebase --i origin/dev-hotfix

To update the non-lead projects to the latest changes, use the rebase command:

git pull --rebase
# or 
git pull lead --rebase
# or 
git pull lead dev-hotfix --rebase
# or
git fetch lead && git rebase lead/dev-hotfix