Monday, February 19, 2018

Pure Git with Convention over Git

Implementation of remote Git repositories synchronization by pure Git and the Convention over Git.

This approach uses well-known Git tools. It is because Git has an innate ability to do this. All we need to add is some convention.

Working solution on GitHub

The situation


Say, we have teams in separate companies. Each team owns their own repository hosted on their own separate git server. This often happens for vendor-client scenarios.

The targets

  • Create a single force, a single team.
  • Eliminate severe and constant errors as a result of disunity.
  • Eliminate significant time wasting.
  • No single repository, no team's heart beating.
P.S.:
I even call this approach as Conventional Distributed Version Control System over Git.

Saturday, February 17, 2018

Approaches to synchronize remote Git repositories

Pure Git

Implementation: Pure Git with Convention over Git

It uses pure Git techniques.
This one is more academic but fully working.
Has some limitations.
Has the smallest amount of implementation dependencies.
*nix & Windows ready.

Stateless Analysis

Implementation: git-sync

The best approach. But it has more implementation dependencies: gawk, modern bash.
*nix & Windows ready.

Stateful Analysis

It depends on collected information about Git refs.
It has a wider set of conflict solving tools.
Predecessor of all other approaches.
Requires a modern software language, an IDE and good programming practices.

Implicit Renaming of Refs

My beloved.
Belongs to the Stateless Analysis.
It implies convenient manual conflict solving on the run.
It is kinda Git inside the Git with an additional degree of external references.

Friday, February 16, 2018

Glossary of synchronization of remote Git repositories

Convention-Over-Git
One of the approaches to automatically solve conflicts of synchronization between remote Git repositories.


fast-forward
safe, non-overwriting git fetch or push.

non-fast-forward
unsafe, forced & overwriting git fetch or push.

side
directly related one remote and many local git repositories. They are located on one side, i.e. in one company.

owner
owner of the side. A team that owns and uses their remote repository directly.

refs
git references, mostly such as branches and tags.

conventional refs
refs strictly separated by a convention and pertaining to different different sides. Each side owns its refs but can modify refs of another.

prefixed refs
This is a naming convention and an implementation of conventional refs by prefixes.
As an example:
"company1/some_feature", "company2-develop"
where the "company1/" and "company2-" are the conventional prefixes.

refspec
It specifies source and destination refs and can specify a non-fast-forward Git-fetch or -push by the plus "+" sign at the beginning.

synchronization interval
It is an interval between two synchronizations of remote Git repositories. Usually it is from one to three minutes.

reflog
Git Garbage Collector.

agentsync-agent
synchronization agent. Some implementation that doing all the work.

Saturday, September 30, 2017

Day-to-day use of Convention over Git

This page explains how to use the Conventions over Git on a daily basis.
Or how to live with Git remote repositories auto synchronized by the Convention over Git.

How to work with the Convention over Git

Use Git, as you always do, except for the following.
  • Name branches and tags with a prefix of your side (as an example "company/some_branch_name").
  • Do plain commits to prefixed branches of your side.
  • Delete only branches and tags of your side. Deleted by you refs from other sides will be recreated automatically.

How to migrate your work to another side refs

All refs will be updated on all sides automatically.
But when you will want to migrate your work to another side, you will do one of the following.
By a merge or cherry-pick from your side
  1. Do a plain merge from you prefixed branch to a prefixed branch of another side.
  2. After a synchronization interval do "git fetch" and check your merge-commit is still there.
  3. If not, then just repeat everything.
This is not a problem, really. Your local Git repository always preserves all local branches (it even stores deleted commits in the Git's reflog).

Commits between different sides may disappear if somebody else do a "git push" to the same branch before you.
The auto conflict resolving of Convention over Git will delete your merge-commit only in a case of non-fast-forward differences. This is not so often.

By a merge or cherry-pick at another side.
Nobody doing so :-)
This works if your can connect to a remote Git repository of the other side.
Wait the sin—Āhronization interval and your commits will appear on the remote repository of the other side.
Do a merge between branches there.
Now this is safe. No checks, no worries. Done.

By a plain commit on your side to an other side ref.
Junior developers doing so. Prevent this.
If you feel lucky you can do a plain commit directly to a branch of the other side.
Again, you must recheck you commit is still there after a synchronization interval.
And if you're unlucky then you'll end up searching your commit in the Git-reflog. It is time wasting operation. I warned you.
So, be careful or inform guys on the other side.

Out of convention refs

In the provided implementation mode of the Convention over Git, the sides only see conventional (prefixed) refs.
Not-prefixed branches and tags will stay undisclosed for other sides. They even can have the same names on different remote Git repositories.

Convention over Git

Convention over Git allows automated conflict solving during automated synchronization of remote Git repositories.

Naming convention
It is any prefixed name. Each remote Git repository owns its prefix and non-fast-forward conflicts for prefixed Git refs will be solved in favor of an owner.
Examples
company1/develop, company2/develop
company1/JIRA-123, company2/JIRA-321


Thursday, September 28, 2017

Cheat-sheet of implementation for Convention over Git

This is a cheat-sheet for the simplest implementation of the Convention over Git.
It is used for an automated synchronization between remote Git repositories.

If you understand the idea of the Convention over Git, then it is easier to look at this cheat-sheet. Otherwise look at the Convention over Git article.

Here we'll start.
Let's say some two development teams in companies "A-1" and "B-2" want to auto-synchronize a Git-repository named "repo" with each other.

We have some preconditions:
  • The teams want to synchronize only conventionally named branches. Not the entire repository, which is also possible.
  • GitLab of one of the teams automatically blocks tags deletion. So, they decided to exclude Git-tags from syncing.
  • Guys have no time for optimization and struggle with GitLab, they just want a working solution.
  • Logic below uses bare repositories (sync-repo) hosted on some your synchronization-agent machine.
  • They have a side effect "do not push to another side branch more than once a minute".

In every synchronization cycle we shall do:


Creating a bare repositories of a synchronization-agent, if they do not exist. One for each side (team).


Checking if there are changes in remote Git repositories. Interrupt if not.

git ls-remote --heads  https://git.a1.com/repo  a1/*  b2/*
git ls-remote --heads  https://b2.com/git/repo  a1/*  b2/*


Updating repositories of synchronization-agent. (the first)

# for a1 sync-repo
git fetch --prune https://git.a1.com/repo  +heads/a1/*:heads/a1/*  +heads/b2/*:heads/b2/*
# for b2 sync-repo
git fetch --prune https://b2.com/git/repo  +heads/a1/*:heads/a1/*  +heads/b2/*:heads/b2/*


Checking if the Deletion & Recovering is allowable. Use git show-ref and git show to do this.

Each repository at least must have a branch with the same sha-1 and also some fixed commit.
Scip Deletion & Recovering if there are no differences in current ref-names (without sha-1).


Deletion & Recovering of refs (also a partial fast-forward synchronization as a side effect).

# from a1 sync-repo
git push --prune https://b2.com/git/repo  heads/a1/*:heads/a1/*
# from b2 sync-repo
git push --prune https://git.a1.com/repo  heads/b2/*:heads/b2/*


Updating repositories of synchronization-agent. (repeat of the first)


Plain syncing of refs

# from a1 sync-repo
git push https://b2.com/git/repo  heads/a1/*:heads/a1/*  heads/b2/*:heads/b2/*
# from b2 sync-repo
git push https://git.a1.com/repo  heads/a1/*:heads/a1/*  heads/b2/*:heads/b2/*


Updating repositories of synchronization-agent. (repeat of the first)


Resolving conflicts of conventionally named refs. Do non-fast-forward pushes.

# from a1 sync-repo
git push https://b2.com/git/repo  +heads/a1/*:heads/a1/*
# from b2 sync-repo
git push https://git.a1.com/repo  +heads/b2/*:heads/b2/*

All-in-one working implementation

You can test an all-in-one implementation in a project that have I published on GitHub.
It creates local and remote repositories in the project folder, so you can easily emulate and play with Convention over Git on your own.

Sunday, November 13, 2016

"box-sizing" CSS property. Fairness somewhere near.

Bootstrap 4 has selected the initial Internet Explorer CSS box model.

Oh my goodness, there is even "International box-sizing Awareness Day" out of there. "DOWN with big content-box, BORDER-BOX 4LIVE".
It's such a boon for developers that here at CSS-Tricks we observe International Box-Sizing Awareness Day in February.

Look, Bootstrap really uses it _reboot.scss

// Reset the box-sizing
//
// Change from `box-sizing: content-box` to `border-box` so that when you add
// `padding` or `border`s to an element, the overall declared `width` does not
// change. For example, `width: 100px;` will always be `100px` despite the
// `border: 10px solid red;` and `padding: 20px;`.
//
// Heads up! This reset may cause conflicts with some third-party widgets. For
// recommendations on resolving such conflicts, see
// https://getbootstrap.com/getting-started/#third-box-sizing.
//
// Credit: https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/

html {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

And I cannot fail to mention a handy demo (it wasn’t created for Bootstrap 4, it just shows how box-sizing generally works).

Unbelievable. Were Internet Explorer developers near to front-end people those 15 years ago?



Detailed view on Box Sizing - https://css-tricks.com/box-sizing/
W3C vs IE. Time has showed))