2

We are using Git in our organization to update codes on the servers for all projects. Often, developers forget to ignore the files which should be ignored (like db config or data etc.) and push them to our Git server. Which later gets synced to the actual server where code runs (with the help of hooks). git pull is executed on the server to get the latest code.

Now, if I add any specific file to .gitignore and remove it from index and push it to the server using below commands.

git rm --cached config.php
git add .gitignore
git commit -m "removed config file and ignored it"
git push origin master

This will remove the file from Git but not from my local repo. It will also prevent it from being tracked further.

Then, git pull is executed on the server which is removing the newly ignored file causing issues. Simple pull command is executed on the server as below:

git pull origin master

I do not want to remove config.php file from the server while removing it from git remote repository.

Sometimes I remove large number of files in the same way which should remain on server (where code runs).

What would be the easiest and programmable solution for this ? I have developed a Node.js program which logs in to the server and runs pull command there programmatically.

AlBlue
  • 23,254
  • 14
  • 71
  • 91
shashwat
  • 7,851
  • 9
  • 57
  • 90

1 Answers1

2

You can't; you're recording the deletion, and the deletion is occurring when you do the update. This is in fact what you'd want to happen if you committed a file that you didn't want there; you wouldn't expect it to be left hanging around afterwards.

If you really want to prevent this happening, write a commit hook on the server that verifies the commit doesn't add anything at those explicit path(s) that you don't want them to commit, and ban any such commits from being pushed in the first place. That way the developers will have to resolve their commits locally.

Note that 'adding a new commit which removes the file' isn't sufficient, because the interim commit will have already added it. It is necessary to squash that deletion commit with the commit that added it accidentally in the first place.

How you educate your users is a separate question ...

AlBlue
  • 23,254
  • 14
  • 71
  • 91
  • You are correct. I understand how it works and its fine. Wouldn't squashing commit rewrite the history ? I don't allow developers to do a force push to prevent overwriting other's work. – shashwat Aug 28 '15 at 11:26
  • You have to get the developers to do the squash on their own local machine before upload. If you write the commit hook, they can't corrupt the central repository. They can then rebase theirs onto latest so they won't corrupt the history of the shared repository. – AlBlue Aug 28 '15 at 11:28
  • You said `write a commit hook on the server`, but in most cases, first commit is made from the developers's local system. And then it is cloned to the server from our Git server. – shashwat Aug 28 '15 at 11:29
  • Okay, but we have 100's of project. It is not possible to create commit hooks (those are specific to the projects) for every project on developer's system before a developer do a `push`. – shashwat Aug 28 '15 at 11:37
  • Is there a way to configure some file patterns globally (for all projects) on Git server so it would not receive commits which add/change files which match with any of these patterns? My server is `Gitlab CE`. – shashwat Aug 28 '15 at 11:52
  • @shashwat Would putting the `config.php` in a submodule work for you? This way it is both in origin and local but you will never forget to add it, because it is in a submodule which is tracked separately. Calling it `config.git` would look fine too. You can even create one `config` submodule for all repositories you have and manage those files in a tree structure organized 'per-project'. On the other hand - developers will forget to run `git submodule update`. Perhaps devs shouldn't forget? :) – Zloj Oct 13 '15 at 11:12