Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Share code between branches in different folders

Tags:

git

I have one repository with two branches (master and gh-pages). The folder structure of my master branch looks like this:

/dist
    /js
    /css
/other-folders

In my gh-pages branch, I have an _include folder with some files in it. I want to share my code in the /dist/css and /dist/js folders with my gh-pages branch, so that my gh-pages folder structure looks like this:

/_include
    /js
    /css

or

/_include
    /dist
        /js
        /css

Is something like this possible with git? I can't just use

git subtree push --prefix dist origin gh-pages

because that will just copy the /dist to another /dist folder in my gh-pages branch

like image 734
Daniel Avatar asked Mar 01 '16 22:03

Daniel


1 Answers

Yes and no.

Yes, you can share subdirectories between branches - git does it all the time.

No, you cannot keep them in sync automatically with regular git commands.

Unfortunately, I am not close to a shell right now so i cannot provide the commands, but I will show you the way.

Git has three basic data structures:

  • blobs are objects that contain the actual raw byte streams of your files or other things.
  • trees are objects that describe a directory, just like in a regular file system. They contain the hashes of blobs together with their filename, mode etc.
  • commits are objects that contain the hash of a tree object and assorted information like author, timestamp, parent commits etc.

These three things are literally each a file within .git/objects, with a file name equal to their content hash.

For your problem, the key is that these objects build a read only directed acyclic graph just like you are used to from the commits.

You are interested in the trees. After fiddling around with git cat-file, you can take a look at some tree objects. You will notice immediately how it would solve your problem if you were able to hack your _include tree so it contains pointers to the trees from that other branch. Note that in this deep level it is completely natural to share trees between commits and branches, git does it all the time. Amongst others, this is the reason why repositories take up relatively small space and also why git is sometimes called a distributed file system.

Now, there are two adventures left for yourself:

  • Find out how to fake a tree that looks like you wanted. As I said I do not have a shell now, but you should be able to figure it out with the examples in https://git-scm.com/book/en/v2/Git-Internals-Git-Objects which show how to read and write individual objects.
  • Unfortunately, due to the nature of these read only data structures, you have to re-build your _include tree everytime one of the included trees changes since that will also give them new hashes. Your probably guessed it - nothing can actually ever change any git object. Changes are always brought in by creating new objects. This should not be a big problem though, you can create an appropriate hook for your script which automatically creates a new tree for you.

Frankly though, as fascinating as all of this is, you might just as well forget everything I just said and simply recreate the _include from scratch with git porcelain commands in a hook everytime a commit touches the source directories, by checking them out from the source branch, copying then over (with cp, not some special git command) and comiting them in the destination branch. Git will actually automatically figure out that those subdirectories are the same as what it already had in their respective objects, so the end result will actually be exactly the same as if you had created the tree object yourself!

like image 97
AnoE Avatar answered Nov 12 '22 00:11

AnoE