Reputation: 10377
The build workflow of a legacy project should checkout a specific git version tag and compile that sources.
I proposed to keep it simple and use Git Cli like that:
git clone –b $versiontag –singlebranch $gitrepouri
instead of git clone and git checkout tag afterwards.
To "save time", a colleague wants to use another approach = copy the .git folder from an existing Git repository at another server to the build working dir and afterwards operate on that folder.
At first she tried with git checkout $versiontag
after the copy.
The output has multiple entries like:
$ git checkout tags/sometag
D Foobar/somefile
D Foobar/someotherfile
[...]
Note: checking out 'tags/sometag'.
You are in 'detached HEAD' state.
[...]
but the working tree content differs from a normal git clone and git checkout, though both suppose to be in
the detached head state and have checked out that specific tag.
Also there were problems with tools like Sonarqube, because git blame didn't work
(Missing blame information..).
Afterwards she tried with git sparse-checkout
after the copy, and that seems to work
at first sight -
though it's much more complicated and complex compared to the simple Git Cli approach.
What are the drawbacks of using Git commands against a Git repository without working tree overall ?
Upvotes: 0
Views: 1690
Reputation: 488163
Git has an internal setting to tell itself that it's using a clone with no work-tree. Specifically, core.bare
should be set to true
for such a repository.
Copying a repository manually, rather than using git clone
to copy it, copies its configuration files (.git/config
and .git/info/
files). This includes the core.bare
setting and several settings that Git creates on its own to describe the behavior of the machine and file-system on which Git is running. If these settings do not reflect the actual machine and actual file system, things may go wrong in various ways. Some of the info
files may point Git into additional directories not copied; if so, you need to know what to do about these as well. So, unless you know what you are doing with respect to these other variables and info
files, do not use cp -r
(or tar
or similar) to copy the .git
directory directly.
Copying the raw .git
repository also copies the index for that repository. The index describes the work-tree, so the copied index is automatically incorrect if the new location has no work-tree. (Note: all repositories, including bare ones, have an index. The index for an initially-bare repository is normally empty, but see below.)
That said, you can do some Git operations on a bare repository. Specifically, you can do any operation that does not require a work-tree. This means that if you know what you are doing with respect to the special control variables, you can copy a .git
repository elsewhere and then use it. Since you will be avoiding operations that use the work-tree—which means avoiding git checkout
, for instance—the broken index is not a problem, although if you're going to be this clever, which is perhaps too clever by half, you can also just know when it is safe to remove the broken index.
You can also supply a temporary work-tree for a bare repository, using git --work-tree=<path> ...
or GIT_WORK_TREE=<path> git ...
. If you do this, that overrides the core.bare
setting, and the bare repository's index is used to keep track of the given <path>
. Note that if you change paths, you invalidate the index; in this case, you must either use another index (by setting GIT_INDEX_FILE
to an alternate index) or remove the existing index.
So, with all the above caveats in mind, you can convert a .git
directory to a proper bare Git repository, or use cp
or tar
to transplant a .git
directory including or excluding its current work-tree to a new location with a new work-tree. But in general, you shouldn't, because if you do this, you must make a lot of assumptions about future versions of Git. Git promises that git clone
and git bundle
and the like will keep working the way it does now; Git does not promise that sneaky surgery on a copied .git
directory will keep working this same way.
Upvotes: 2