Working with microservices and GIT
Microservices are still pretty popular in our industry since they imply lots of benefits. However working with that kind of architecture might be annoying when it comes to commit the changes using GIT. Why? Simply because in a common approach, each microservice should be put in a separate repository. Therefore, instead of doing your typical “GIT sequence” once, you end up with few terminals where you do pretty much the same job. Fortunately, you can avoid that with no big deal.
Imitating “common approach”
Let’s start with creating some repositories on Bitbucket. Each one will represent one microservice. I created just three of them since it’s fine for explaining the idea:
In each repository, I put the text file which will be tracked by GIT so any changes will require making a commit.
Creating GIT submodules
We got to the point where we should discuss how will we deal with managing our code in GIT. The answer is – submodules. If you have never heard about this, the official docs should help you out:
Submodules allow you to keep a Git repository as a subdirectory of another Git repository. This lets you clone another repository into your project and keep your commits separate.
Let’s try that in action. First of all, we need to clone one repository from Bitbucket. This one will become our main module so, you should think which one to choose. In the example, repository-a will be the main, so I type in terminal the following command:
git clone https://GooRiOn@bitbucket.org/foreverframe/repository-a.git
After few seconds, I have my repo clonned. It contains nothing more but a mentioned text file. Now, let’s add our submodules, so repository-b and repository-c:
cd repository-a git submodule add https://GooRiOn@bitbucket.org/foreverframe/repository-b.git git submodule add https://GooRiOn@bitbucket.org/foreverframe/repository-c.git
Before we move forward, we’d better check what actually happened. After executing the above commands, you should spot that new file appeared inside main module called .gitmodules. Here’s what it contains:
[submodule "repository-b"] path = repository-b url = https://GooRiOn@bitbucket.org/foreverframe/repository-b.git [submodule "repository-c"] path = repository-c url = https://GooRiOn@bitbucket.org/foreverframe/repository-c.git
As you see, inside this file we have an information about each submodule in our project (so name, path, and URL). Nothing special here. What’s worth to mention is that besides the .gitmodules file there are also two new catalogs inside repository-a so the main module. Each one contains the entire code from submodule. Let’s push our changes:
//inside repository-A git add -a -m "added submodules" git push
Now, we can go back to Bitbucket and see what we’ve got:
Clicking on chosen submodule catalog will take you straight to its repository on Bitbucket.
Doing changes in GIT submodules
Let’s say that we did some changes in one of our submodules and we want to commit our changes. What should we do? Well, it turns out that that GIT offers a very useful command to perform an action on each submodule:
git submodule foreach '<command_to_peform>'
So, it seems that in our case it’d be:
// inside repository-a git submodule foreach 'git commit -a -m "added some changes"'
However, it will work only in some cases. The thing is that committing the repo without changes will end up with non-zero status code (so you can treat that as an error) which will terminate the whole foreach. Therefore, if your first submodule will not contain any changes, the loop will be stopped during the first iteration. We should come up with something that will simply, “skip” the repository with no changes. And here’s the solution:
// inside repository-a git submodule foreach 'git commit -a -m "added some changes" || :'
Yep, all we did was adding 5 characters (whitespaces included 😉 ). The difference between these two commands is that the second will perform null-command (:) if first one (commit) fails. This will not terminate foreach. Of course, similarly you can push your changes:
// inside repository-a git submodule foreach 'git push'
Having this done we need to also commit and push main module:
// inside repository-a git commit -a -m "some changes" gitp push
Cloning main module from Bitbucket
The last thing we need to discuss is cloning the entire project (so the main module and submodules) by other folks. Here’s the command for our example:
git clone --recursive https://GooRiOn@bitbucket.org/foreverframe/repository-a.git
If you want to pull all changes you can use the following line:
// inside repository-a git submodule update --recursive --remote
As you see, you only need to clone main module and use the –recursive flag to fetch depended modules inside.
Of course, this is just one of the possible approaches. The commands are not the shortest, but aliasing, in this case, might help a lot to make your work even faster.