12

There is a remote repo with directory structure:

-directory1
    -file1_1
    -file1_2
    ...
-directory2
    -file2_1
    -file2_2
    ...

I have a folder on a web hosting with a custom name, say, "/path/public_html".

How do I set up git on the web hosting, so my "public_html" tracks a subdirectory "directory2" of a remote repo?

So, in other words, I want to execute some form of git command on the web hosting and update public_html to the latest content of "directory2". I don't care about pushing back to repo from web hosting, if it helps.

Gleb Varenov
  • 2,795
  • 3
  • 18
  • 18

4 Answers4

13

You cannot clone directly directory2 content, only directory2 and its content, meaning you always have a directory2/ folder on your disk.

If you want to see directory2 content in public_html (meaning not public_html/directory2/...), then you need a symlink.

That being said, you can still clone and checkout only directory2 folder, instead of cloning the full repo, as described in "Is it possible to do a sparse checkout without checking out the whole repository first?"

That is:

git init /a/path
cd /a/path
git config core.sparseCheckout true
git remote add -f origin /url/remote/repo
echo "directory2/" > .git/info/sparse-checkout
git checkout [branchname] # ex: master

That would give a a/path/directory2 folder, than your public_html can symlink to.

If having a directory2 folder in public_html does not bother you, then you could repeat the above commands in public_html instead of a/path.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
6

how about cloning the entire repo on the host and use symlink between directories public_html -> directory2

shahaf
  • 4,750
  • 2
  • 29
  • 32
  • I hope to find a less messy solution, but thank you. I will keep the idea in mind. – Gleb Varenov Jan 24 '18 at 12:31
  • you can use sparse checkout to clone only specific directories https://git-scm.com/docs/git-read-tree#_sparse_checkout I think it's more complicated than the above thu – shahaf Jan 24 '18 at 12:36
  • A symlink is the simplest, most obvious solution. The only reason I would consider anything else is if you're really space constrained, and your git repo has lots of other junk in it. (In that case, you should really consider splitting your repo, though) – Jonathan Hall Jan 31 '18 at 09:09
4

This is straightforward git read-tree work. Make a bare git repo on the webserver, anywhere. Keep a manifest aka index for what's in your deployment directory and handle your updates with a pre-receive like so:

#!/bin/sh
while read old new ref; do [[ $ref = refs/heads/deploy ]] && {
    export GIT_INDEX_FILE=$GIT_DIR/deployment-manifest
    export GIT_WORK_TREE=/path/public-html
    git read-tree -um `git write-tree` $new:directory2 || exit 1
}; done

Then push what you want deployed to the webserver's deploy branch, e.g. git push server master:deploy

git read-tree loads the index, which is a manifest, a list of what was put where in the worktree, from any tree in the repository's object database. It reads the tree you name into the index. It's the workhorse for checkout and reset and merge, for instance with the -um option it's what updates the worktree for a checkout or fastforward merge. You can keep any indexes you want, for any content you want. The convenience wrappers keep one index, for one set of content, and always update a reference named HEAD to match whatever they're working with, but that's purely conventional.

Note that if some file being deployed this way has been changed in the deployment tree, the git read-tree here and the push will fail because git won't overwrite content you haven't told it about.

jthill
  • 55,082
  • 5
  • 77
  • 137
  • I always forget about that kind of command (read-tree here): +1 – VonC Feb 07 '18 at 05:39
  • ( I don't really understand this answer. Oh, well. What are the advantages over sparse checkout and symlinking? I see that you keep actual repo on webserver separated from /path/public-html, but after this things are murky. what and how do I write to deployment-manifest? what would be my command to update webserver files to match remote repo? I assume 'git pull' will not suffice. – Gleb Varenov Feb 07 '18 at 13:35
  • Those commands already do what you want, see the edit. Advantages: you get exactly the content you want, in exactly the location you want. – jthill Feb 07 '18 at 16:31
  • Apologies. While marveling at ingenuity of this answer, I gave the bounty to an answer that I could actually put to use, even if it is less perfect. I tried to implement your solution, but I couldn't get it working. I created a repo on webserver with `git init`, assigned remote with `git remote add` and saved the code you provided into a file 'script.sh'. I run the script, it waits for some input and I am uncertain what to do next. – Gleb Varenov Feb 08 '18 at 09:07
  • 1
    What tone are you speaking of? I didn't mean to offend you in any way. The meaning of pre-receive indeed escaped me. Only now, after you pointed at it, and I googled it, I found what you meant. Wasn't aware of git hooks before. Pls don't take it close to your heart, I appreciate your time and effort giving this solution. I just wasn't knowledgeable enough to digest it, which I stated clearly earlier. – Gleb Varenov Feb 12 '18 at 08:42
2

I don't care about pushing back to repo from web hosting

In this case you could use the archive command. Something like this:

git archive --remote=remote_repo --format=tar branch_name  path/to/directory2 > /path/public_html/dir2.tar && cd /path/public_html && tar xvf dir2.tar
dwright
  • 504
  • 3
  • 7