7

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

mrksbnch
  • 1,792
  • 2
  • 28
  • 46
  • What do you mean by share? Do you want them to always be in sync, or be able to push to one from the other? – merlin2011 Mar 01 '16 at 23:41
  • Why not use symlinks? – morxa Mar 02 '16 at 02:22
  • @morxa, OP wants to sync two branches, not folders – TheGeorgeous Mar 02 '16 at 05:08
  • @merlin2011 If it's possible for them to always be in sync, that'd be fine. But I don't mind using a command to push my `dist/js` and `dist/css` folders from the master branch to my gh-pages branch. – mrksbnch Mar 02 '16 at 09:02
  • @TheGeorgeous I want to sync two folders (js and css) between two branches – mrksbnch Mar 02 '16 at 09:10
  • for synchronization between 2 branches, I use submodule: http://stackoverflow.com/a/35307501/6309 – VonC Mar 02 '16 at 09:22
  • @VonC Thanks, but can you give me an example of how that'd work in my case. I only want to include two folders (`css` and `js`) in my `gh-pages` (inside `_include`) branch, not everything from the `master` branch. – mrksbnch Mar 02 '16 at 12:21
  • @demrks you would need some sparse checkout associated to your submodule: http://stackoverflow.com/a/17693008/6309. And certainly a symlink in order to see css in _include. – VonC Mar 02 '16 at 12:41
  • It doesn't directly answer your question, but I think you might be using the wrong tool for the job. Having a `gh-pages` branch is effectively the same as having another repo altogether, so what you really want is to be able to share CSS and Javascript between two repos. There are many ways to do this (subtrees/submodules being my least favourite option), but I believe this would be the scope for another question. – alextercete Mar 02 '16 at 14:00
  • @alextercete Thanks, you're right, but I'm developing a frontend framework for a client. For that, I need to create a CSS style guide, that is build with Jekyll in my `gh-pages` branch. So I need a way to access my generated CSS and JS files (of the `master` branch) from my gh-pages branch. Subtrees and submodules look promising, but I couldn't yet figure out how to include one or two folders of one branch (master) into a folder of another branch (gh-pages). – mrksbnch Mar 02 '16 at 15:02

1 Answers1

3

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!

AnoE
  • 8,048
  • 1
  • 21
  • 36