Most of your concerns seem to relate back to this:
A new commit number is created in the repo. And it appears that the other projects have a new version too.
This is not how version control works, and certainly not how git works.
Firstly, a commit is the state of your source code at some particular moment. It is distinct from a build, which is that source code compiled with particular configuration, external dependencies, and so on.
If you have a version control system that gives each state a unique, incrementing number and you always build with precisely standardised options and dependencies, then you could use that commit number as a "build number".
However, git is not such a version control system: git does not have "commit numbers". A commit is uniquely identified by its hash, which is not an incremental number, but a digest of everything in that commit - the state of all the files, the commit message, author and date, and the hashes of zero or more (but mostly 1 or 2) "parent" commits. For most day-to-day purposes, you can treat commit hashes as random strings; they don't have any meaning related to "versions" of your software.
The other sentence I'd like to comment on is this:
I could use branches but I'm not sure how easy it would be to update the changes every time for each branch.
General wisdom is that with git, branches are cheap. Most workflows using git will have you creating and merging multiple branches every day. I'm not really sure how they relate to your question, though, so I won't confuse things by speculating.
To answer the actual question, all of your options are perfectly fine, and which one you use comes down to a bit of judgement and a fair amount of opinion:
- You are right that in one big repository, changes to any file will create a new commit of the whole repository; but if you run
git log Project_A
, you'll get a list of just those which made changes to that directory. You might decide that having cross-project commits is a good thing: you can make a breaking change to "Libs" and fix the Project code in the same commit. Or, you might decide that the projects have different release cadences, and giving each its own repo makes it easier to have appropriate branches and tags.
- Whether versioning Libs separately makes sense depends partly on your language and build system. You might decide that every change to a library is immediately released as a new tag, named according to Semantic Versioning, and the projects always depend on a tagged version. Or you might decide that it can't be tested on its own, so having the library and the projects always checked out together makes testing easier.
- I'll be honest I don't know much about submodules. They will have their own compromises, which you should read up on, and decide if they're appropriate to you. There's not going to be an easy yes or no from the level of detail you've given.