-1

My main directory structure is /site_program_files/users/usr1

I don't want Git to touch what is in a /users directory and subdirectories... So, I have added /users to my .gitignore file and did a commit then push. And also deleted what was there before with git rm -rf /users.

But now, every time I push it deletes all the files my users updated in their /users directories on the hosted website. All I want is for git not to affect what is in the /users subdirectory on the server, regardless what I'm doing for testing on my local version of it. What am I doing wrong?

Green Chief
  • 91
  • 1
  • 8
  • I guess it's because of .gitignore. It ignores all files, so when you push, it sends an empty folder which replaces folder on server. – Peter Badida Mar 11 '16 at 21:51
  • It's terrible logic this Git s*ht ;-) I just want it not to mess with that subdirectory, what do I do? – Green Chief Mar 11 '16 at 21:52
  • 3
    You asked git at some point to track everything in `users/` and later told it to delete everything in `users/`. It is natural that every clone that takes the "delete from `users/`" commit would delete the `users/` directory; that's what the commit was all about anyway! But from that point on, `users/` would remain untouched. So this is a one-time thing for each clone, and they can always retrieve the files in `users/` from a previous version. – Shahbaz Mar 11 '16 at 21:52
  • 1
    Actually @KeyWeeUsr's statement is quite wrong. `.gitignore` doesn't force a directory to be emptied. It just doesn't show you that there are files to be added. – Shahbaz Mar 11 '16 at 21:53
  • http://stackoverflow.com/questions/10100933/how-to-ignore-files-and-folders-with-pull-requests-to-github-in-distinct-git-clo – Mircea Mar 11 '16 at 21:55
  • So now how do I stop it from always deleting that subdirectory and what is under it in the future? I need to be able to test it locally but not replicate what happens with that subdirectory to the server. It should certainly not delete that subdirectory on the server – Green Chief Mar 11 '16 at 21:58
  • Repeat after me: "Don't push to a non-bare repository. Ever." – Todd A. Jacobs Mar 12 '16 at 01:11
  • @CodeGnome I never did... The first thing I ever did is pull from master. So, any other ideas? – Green Chief Mar 12 '16 at 01:18
  • If you're not pushing to a non-bare repository, then your post is flawed. You are blaming Git (a tool you don't understand) for behavior of something on OpenShift (a platform you don't understand) using a deployment process you don't understand and haven't included in your post. This is not a Git issue, so unless you include the relevant programming-related code, this question is likely to be closed as off-topic *as a programming question.* – Todd A. Jacobs Mar 12 '16 at 04:21
  • @CodeGnome... Look, the gist of it is that Git and or Openshift process has allowed my to get out of sync. Now, I just need a simply way to override that Git-jive and make the remote (hosted version) be the same as what is on my mac. If there isn't a way to do that in Git for these special circumstances than Git does have a flaw... and that started with the .gitignore not ignoring issues I experienced in the onset ;-) – Green Chief Mar 12 '16 at 16:01

1 Answers1

3

(I assume your hosted website has some sort of auto-deploy script. Unless you show this script, we must make some assumptions about it. For now I will assume it consists mostly or solely of a git checkout command.)

Edit: the actual deployment code appears to be a custom OpenShift Ruby script (which is never shown on this linked page): https://developers.openshift.com/en/managing-deployments.html. Someone familiar with OpenShift and Ruby can perhaps comment on what the default deployment script really does. If it's not just git checkout (and clearly it's not), some of the assumptions below are unlikely to hold.

Edit 2: this appears, in the end, to be a question about OpenShift. The problem appears to have nothing at all to do with git.

You can't really get around this in git, at least not without custom hacking. The reason why is simple enough:

  • As far as git knows, you are (on the hosted web site) asking it to move from $old_commit (whatever ID that is) to $new_commit (another ID).

  • So, git compares what's in $old_commit vs what's in $new_commit.

  • The old commit had files users/usr1/foo and users/usr2/bar. The new commit does not.

  • Therefore, git must remove those files so that it makes the correct transition from old to new.

Git will do this every time you move from $old_commit to $new_commit, because those are the instructions needed to convert a work tree from $prev_commit to $new_commit. It doesn't matter that in $new_commit, the files are in .gitignore (which doesn't mean "ignore", really): what matters is that they are in $old_commit and not in $new_commit.

But, we can observe one other thing: with any luck, git will only ever do this transition from $old_commit to $new_commit once. What we need to do, then, is, on the hosted web site:

  1. Move all the precious user files out of the way, so that they don't exist under their original names for a while;
  2. Cause git to do the old-to-new conversion (which should silently "remove" the now-non-existent paths); and
  3. Move the precious user files back.

The drawback here is that if you ever do somehow go back to $old_commit on the hosted web site—or indeed, any old commit that has those files—and then transition it to $new_commit (or any newer commit that no longer has the files), git will remove the files again.

It might be nice if git had an ignore syntax and/or file that marked particular files as "precious, do not destroy, though do not source control either"; but it doesn't (at least, not today).

Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775
  • Luckly, everything in the /users directory on the server is still just testing crap. So at the moment the web-app recreated /users/usr1 from the database. But now if I change something on my mac and commit push again, will it again wipe out those directories? Or will it adhere to that /users in the .gitignore file? I just want to tell it to forget/ignore everything it ever did or will do with /users – Green Chief Mar 11 '16 at 22:09
  • Once the server's current commit is one that does not have the user files in it, moving from that commit to another commit that also does not have the user files in it, git won't *remove* the user files. However, what gets deployed depends on the precise deployment script on the server, which you have not shown, so it's not possible to say for certain. – torek Mar 11 '16 at 22:16
  • So here's what I think might work. Delete the /users and its subdirectories on my mac, then do a git add and git commit. Then recreate /user on my mac, and again git add then commit. Then Git push to the server – Green Chief Mar 11 '16 at 22:24
  • I don't know what you are initially `git add`ing in the comment above. Remember that both `git add` and `git rm --cached` merely adjust the *index* (what will be in the *next* commit). When you `git push`, you transfer commits (not the index) to the pushed-to repository. What that site does with the new commits depends on the deployment script code. – torek Mar 11 '16 at 22:28
  • How can I just get rid of/reset Git (its tracking and repository) and tell it to start over from scratch with /users in the .gitignore and begin with a first add and commit? – Green Chief Mar 11 '16 at 22:58
  • Again, we're all kind of working in the dark, because you haven't shown us what's on the server. All of your issues have to do with what the server is doing, but for all we know, the server could be acting on radio messages from Mars, rather than anything you're doing on your end. – torek Mar 11 '16 at 23:39
  • It's a rails app on Openshift. All my Git commands have been from my Mac since I did an initial pull after initially deploying the app to the server. My only mistake was that I did not add /users to .gitignore from the onset... I dont care about the Git repository... this is still just me myself and I... How can I just reset it to make that initial push again? – Green Chief Mar 11 '16 at 23:44
  • Hm, now we might be getting somewhere. Following some links I arrived at https://developers.openshift.com/en/managing-action-hooks.html - but this is getting deep into RoR territory and I know nothing of Rails and relatively little of Ruby. But it looks like you're supposed to write specific action hooks to make things happen. – torek Mar 11 '16 at 23:53
  • I don't think it's rails based... This to me, it seems like Git BS on the dir/file structure outside of Rails. The users dir is just another dir with text files in it. I just want to get Git to really to it's job and "ignore" it (like I told it to in .gitignore) when I push the root directory. There must be a way,.. – Green Chief Mar 11 '16 at 23:59
  • It clearly is specific to OpenShift. Click on "deployments" and you get to https://developers.openshift.com/en/managing-deployments.html which talks about how to modify their standard deployment script (but does not show their standard deployment script, but it probably is written in Ruby). – torek Mar 12 '16 at 00:03
  • OK, but by default (which is what I chose) Openshift deploy just follows the Git push directives. My problem now is finding a way to get Git to do exactly what .gitignore says, or reset it and have it delete the Git repository and start froms cratch with the right .gitingore ignores – Green Chief Mar 12 '16 at 00:10
  • @GreenChief If starting from scratch is an option for you, then `git-filter-branch` may be your friend. It rewrites the history (beware!) and it's easy to get a history which has always ignored `/users` and never stored anything there. – maaartinus Mar 12 '16 at 00:19
  • @maaartinus ok so what do I type to do that on my local machine? – Green Chief Mar 12 '16 at 00:23
  • You say that it "follows the push directive", but we need to know *what it does at that point*. For instance, suppose that on a `git push`, the default script starts with `rm -rf $target` followed by `git --work-tree=$target checkout $branch`. In this case the target directory `$target` will initially be emptied on every `git push`, no matter what is in the repository. This is what I mean when I say "we need to know what is in the deployment script". (If you look at their examples, it clearly does more than just `git checkout`: we see output like `remote: Waiting for stop to finish`.) – torek Mar 12 '16 at 00:34
  • Now a Git push is removing the /users directory on the server, even it it remains on my local mac. So it's all f*ch*d up. They must fix Git to work better than this... – Green Chief Mar 12 '16 at 00:40
  • 2
    At this point it's not the push itself doing it, and it's not git doing it, it's *something else*. I don't know how to tell you this any better, it's *something in the deployment script* (not git). Git has plenty of flaws, but not this particular one. Given that *it's in the deployment script* you're going to have to *change the deployment script*. Nothing else will help. – torek Mar 12 '16 at 00:43
  • What if I just type Git reset --hard origin/master. Fix the .gitignore, git add it, commit and push to master? – Green Chief Mar 12 '16 at 00:44
  • @GreenChief I used `git-filter-branch` just a few times, so I can't help you more than any random documentation can. But it looks like `--index-filter` could be all you need. Something like `git-filter-branch --index-filter "git rm --cached --ignore-unmatch" /users HEAD` could do. Backup everything first! – maaartinus Mar 12 '16 at 06:26