Push to remote server while excluding some committed files?

ε祈祈猫儿з 提交于 2019-12-05 20:43:55

I don't have a completely awesome solution for you, so I will give you a few options to consider.

First, I have addressed similar situations in the past by using separate branches for production, qa and dev. This does violate your desire for "a single push".

Secondly, if you really want to keep everything in a single branch, you could use another common technique which is to exclude the specific files by using .gitignore, but link to them in each working directory via a soft-link to the varying file. Links are supported in most operating systems, including OSX, Unix-like (Linux, FreeBSD, etc.) and Windows NTFS via the MKLINK command.

To set up using links, you would rename the .htaccess file to be .htaccess-dev and then copy and update it to .htaccess-dev, .htaccess-qa for all your environments. Then, add .htaccess to the .gitignore and finally create soft-links to the correct environment on each of your environments.

For example, if your DEV system was Windows, you would see something like:

C:\code\dev-example>ren .htaccess .htaccess-dev

C:\code\dev-example>mklink .htaccess .htaccess-dev
symbolic link created for .htaccess <<===>> .htaccess-dev

C:\code\dev-example>dir
 Volume in drive C is Boot
 Volume Serial Number is DC8C-D5C9

 Directory of C:\code\dev-example

06/02/2014  06:12 PM    <DIR>          .
06/02/2014  06:12 PM    <DIR>          ..
06/02/2014  06:09 PM                10 .gitignore
06/02/2014  06:09 PM    <SYMLINK>      .htaccess [.htaccess-dev]
06/02/2014  06:08 PM                22 .htaccess-dev
06/02/2014  06:12 PM                23 .htaccess-prod
               4 File(s)             55 bytes
               2 Dir(s)  13,497,245,696 bytes free

C:\code\dev-example>type .htaccess
# Config file for DEV

C:\code\dev-example>type .gitignore
.htaccess

This approach works well for a few varying configuration files, but gets unwieldy if you have many such files, and it doesn't really address your desire for excluding the .less files.

Finally, if you can re-organize your project to separate the dev only code into separate folders, you could use git sparse-checkout on the production server to grab only the folders that you want in prod. In combination with using soft-linked configuration files, this might allow you to have your single-push workflow while maintaining different working folders in dev/qa/prod. See http://briancoyner.github.io/blog/2013/06/05/git-sparse-checkout/

Pushing a commit without certain files is impossible in Git. A commit is identified by the hash of it's changeset and the commit it's based on(which which is in turn a hash of changesets and previous commits). Excluding files changes at least one of the changeset, which in turn will change the hash(unless you happen to hit the same hash, but that is so rare it barely worth mentioning).

However, if might be able to exclude the files from being checked out in the production environment. They'll still be on the production machine, but compacted inside the Git index of the local repository there, where they barely take up any space and don't interfere with anything.

In order for this to work, you need to be able to set up hooks on a bare repository in the production environment you'll push to. Upon a push, you need to use this command:

git archive --remote <path-to-bare-repo> --format tar <branch-to-checkout> | tar --extract --directory <path-to-extract> --exclude <pattern-of-files-to-exclude>

This command, instead of regular checkout, will create a tar archive representation of the branch's current tree. That archive is piped through tar to convert it to actual files on the disc. tar accepts the --exclude flag that lets you specify the files you want to exclude.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!