-1

I know similar questions have been asked multiple times, but I cannot get it to work for my case.

Where I am: I have a local repo that I push to a live server, that included a /content folder and its subfolders. During production that was okay, since I could make changes to /content and just push them. But since this is a website using a CMS all changes to /content will now be produced remotely.

Where I want to be: I now want to 'detach' /content and its subfolders from the code base, so that I can delete the hefty /content folder locally without it being deleted on the live server. That way I still would be able to make changes in the code and push them to the server, while people are able to use the CMS to create files and changes in the /content folder.

So what I did so far:

  1. added the folder to .gitignore:

/content/

  1. removed the folder from the index:

git rm -r --cached content/*

  1. tried to set assume-unchanged so that on push, the files in /content would not be deleted from the live server:

git update-index --skip-worktree

When I do this, I of course get a:

fatal: Unable to mark file

Since the files are in .gitignore, and they need to stay there, such that the folder will be ignored in the future. So what do I do?

lthz
  • 113
  • 1
  • 7
  • Ok, when I initially read this I gathered that you ran your 3 steps on the origin (and my answer is partially based on that understanding), but from comments on other answers I'd say it's unclear. So: on which repo (origin, or a local clone) did you run these steps? – Mark Adelsberger May 23 '18 at 12:58
  • Okay, so the remote is a bare repo I just pushed to the whole time, that is all. I only ever worked with the local repo, which is origin/master since I cloned from the CMS repo. This is also the one from which I rm'ed and so forth – lthz May 23 '18 at 13:37
  • I would be perfectly happy with a solution where I delete the folder completely and add it afterwards while ignoring it for future commits, but that doesn't seem to work either (I tried deleting the folder, committing and pushing, then adding to gitignore and removing from index and adding back in with add --force, but when I delete the folder on local after that, the changes are untracked for commit, even though being ignored and removed before). I know I have a very poor understanding of git but it just seems unreal that it be nowhere near possible to do any of this. – lthz May 23 '18 at 13:49
  • Okay... if the remote is bare, then how are you updating the production server? You say in the question you "push to a live server"; that would mean that the server is a non-bare remote. – Mark Adelsberger May 23 '18 at 13:53
  • I just do git push , and set it up initially as a bare repo, since that is what is recommended for deployment, which I learned now, is not recommended at all. So maybe it is a non-bare but when I do git status on the server it tells me there is no repo. So, well, I'm lost. Pushing does work without any problem, however. – lthz May 23 '18 at 14:01
  • remote.origin.url=https://github.com/getkirby/plainkit.git remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* branch.master.remote=origin branch.master.merge=refs/heads/master remote.live.url=<...> remote.live.fetch=+refs/heads/*:refs/remotes/live/* Where live is the remote server I am talking about. – lthz May 23 '18 at 14:09
  • If someone recommends a bare repo for deployment, then they must also recommend a procedure for setting that repo up so that when it receives a push, it will update the working copy on the server. Do you know what other steps you took to set it up, or have documentation of the recommended setup? Did you use a server-side hook maybe? – Mark Adelsberger May 23 '18 at 14:10
  • I specifically remember to want to avoid setting up a hook. In post-receive, I see this: while read oldrev newrev refname do branch=$(git rev-parse --symbolic --abbrev-ref $refname) if [ -n "$branch" ] && [ "$target_branch" == "$branch" ]; then GIT_WORK_TREE=$working_tree git checkout $target_branch -f NOW=$(date +"%Y%m%d-%H%M") git tag release_$NOW $target_branch echo "..." fi done – lthz May 23 '18 at 14:20
  • No, never mind, I am stupid. I did what is said here: https://gist.github.com/Nilpo/8ed5e44be00d6cf21f22 I cut that bit out of the post-receive I just posted because i deemed it not relevant. So the hook is just: GIT_WORK_TREE=/path/to/webroot/of/mywebsite git checkout -f – lthz May 23 '18 at 14:38

3 Answers3

0

Updated to reflect correction from OP, that the updates had been done on the local clone rather than the server, and that the server is a bare repo with a hook that updates the working folder via checkout -f


The index flags (skip-worktree or assume-unchanged) are not the solution to the problem, but your understanding of why (that it has anything to do with .gitignore) is not correct either. Rather, those flags are set on the file's entry in the index; you can't set the flag on those files because you removed the files from the index.

You clarified that the three steps you mention (create .gitignore, run rm --cached, attempt to set index flags) were done on the local clone. So the next question would be how to sync this up with the server, without deleting the server's content directory.

The index, like the worktree, is local. So the server isn't yet aware that you've done anything. The next time you do a commit and push it, you'll need to take steps to properly update the server (or else the content directory will be lost). I recommend doing this now, so that you don't have additional changes to juggle at the same time (and so that you don't forget to do the extra steps).

You'll need to jump back and forth between the local and the server, so I'd go ahead and open a shell on each.

On the server, you need to prevent the worktree from being automatically updated by the upcoming push. Because your server-side repo is bare and the update occurs by way of a hook, disable the hook. (Either move the post-receive script out of the hooks directory, or edit it and comment out the lines that checkout the changes.)

Now locally you need to stage the .gitignore file and commit the changes (which will include the removal (from the index) of the content directory), and push:

git add .gitignore
git commit
git push

Now on the server you need to sync up the work tree, and re-enable the hook. Since the only change (other than suppressing the content folder) was the .gitignore file

git checkout --work-tree /path/to/webroot -- .gitignore

will sync things back up. Then undo whatever you did to disable the hook.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • Okay, thanks for the clarification and the proposed solution. I was in fact doing this locally, not remotely, and then just wanted to exclude /content from any further commits and pushes. For some reason my remote repo tells me there is none on git status, even though .git is inside my cd. I will get back to you as soon as I figured something out. – lthz May 23 '18 at 13:14
  • @lthz : Alright... well, I'm going to rewrite this answer in light of that information. – Mark Adelsberger May 23 '18 at 13:29
  • Thank you for the explanation. I ended up redoing the repo on the remote server because I could not get it to work this way. I still really appreciate your effort and understand that it should work in theory. It is a messy setup after all. – lthz May 23 '18 at 17:17
-1

Just to clear concept of gitignore first,

  • .gitignore file says i will not detect these files and folder as a part of version controll system.
  • If file is already part of version control system and if you try to ignore then it wont be ignored.
  • You can not ignore file which are part of remote repostiory. Only when you delete it from remote repo and add the folder in gitignore then it will be ignored. Note : YOu wont have content/ on remote repo in this case.

Best Solution :

Let it be on remote repository and you do not commit the files of this folder.

Hope it adds value to your question

RoshanKumar Mutha
  • 2,235
  • 1
  • 12
  • 13
  • Yes I know the basics of how gitignore works, that’s why I rm —cached them locally and tried to flag them assume-unchanged. Unless I am misreading your answer, the last part is what I want to do but with previously tracked files. So how? – lthz May 23 '18 at 11:17
  • I did a commit with the folder deleted to the live server and adding it to the git ignore. Then I added it back in again via force add to commit it again and push it to the server. I will see if that works. – lthz May 23 '18 at 11:19
  • "I did a commit with the folder deleted to the live server and adding it to the git ignore. Then I added it back in again via force add to commit it again and push it to the server. I will see if that works" wont work. Only Solution: Keep it in remote repo and you dont commit any changes by not adding to staging area. – RoshanKumar Mutha May 23 '18 at 11:27
  • Yes that is exactly what I want to do. But how 'keep' them when they are already there and being tracked. – lthz May 23 '18 at 11:32
  • Only files which you add using "git add " can be committed and you will see them if change. Only you need to make sure you do not add them to staging area using git add whihch later get commited using "git commit". Its developer precausion. – RoshanKumar Mutha May 23 '18 at 11:35
  • Yes, I know that. – lthz May 23 '18 at 11:36
  • Having a folder under the worktree, that is not otherwise recognized by the repo, is not a very robust solution. In any event this answer and discussion doesn't address how to get there from the current state of the repo – Mark Adelsberger May 23 '18 at 13:04
-1

You shouldn't use git as a deployment tool.

What you could do: have a remote repo without the content folder. Add content folder to .gitignore. Have your live server pull from that remote repo. This will not change the content of your content folder.

Alternative: have your content somwhere outside your git-folder.

Edit: To solve you problem: do the following on the remote:

git rm -r --cached content/*
git commit -m "content deleted"

then backup you local content folder and git pull.

Fabian S.
  • 909
  • 6
  • 20
  • I will note that for the future, and I see why. But it must be possible to exclude a folder on both sides after the fact. After all it is perfectly possible to do locally. – lthz May 23 '18 at 11:52
  • No it is not. You could do git rm -r --cached content/* on the server, and pull it to your local (which would remove you local copy of content, but you can backup it). But if your only access to the live server is git, then there is no way. – Fabian S. May 23 '18 at 11:54
  • So does that mean that the server has a different index than my local repo? Such that I rm the folder on remote and it will not update it on push/pull? – lthz May 23 '18 at 12:04
  • @lthz - Each repo has its own index, yes. But no, a repo's index does not govern what is updated on push/pull in the way you seem to be indicating. The index means "what's staged for commit from this repo" – Mark Adelsberger May 23 '18 at 13:02