-1

Many apps store their settings in a file under ~/Library/Preferences. I want to version these files in my dotfiles repo. I like my dotfiles repo to be in its own tidy folder so my general approach to versioning configs is to move the config file to my repo and then symlink it from the original location. This also allows me to rename the file to something convenient, even if the original developer picked a bad name for the config file. However this doesn't appear to work consistently on Macs - sometimes the symlink itself gets overwritten, sometimes setting the symlink to "Locked" fixes that and sometimes no.

I find recommendations to symlink the directory itself rather than the file. However the Preferences directory is huge and I don't want to version the whole thing. How can I reliably symlink files in the ~/Library/Preferences?

  • 1
    Usually these files aren‘t meant to be manually maintained. If you need/want to keep old versions, use a versioned backup like Time Machine. – nohillside Mar 24 at 19:43
  • @nohillside I prefer to use free and open source tools. – Donentolon Mar 24 at 23:50
  • Time Machine comes free with any Mac :-) But I‘m sure there are similar backup tools in the OSS world. – nohillside Mar 25 at 5:36
  • @nohillside free and open source – Donentolon Mar 25 at 16:57
2

How can I reliably symlink files in the ~/Library/Preferences

Don't.

These files are generally not for user consumption. They are the support files for the applications you use every day. Some are nothing more than configuration files while others store data like (Firefox) recently visited sites, bookmarks, etc.

I want to version these files in my dotfiles repo.

Why? Unless you're a dev, there's no reason to version these files especially since some change not just daily, but as you use the app.

This also allows me to rename the file to something convenient, even if the original developer picked a bad name for the config file.

Again, this isn't meant for general consumption and second guessing the developer and their naming conventions can cause issues. For instance, many applications upgrade by simply downloading only the changed files while others download the whole application and simply overwrite what was there (Firefox is a good example). Either way, it's expecting it's support files to be where the dev said they would be. There are also many cases in which the config file must be migrated as it uses a different format and the "tools" which the dev implements to do this migration may not be expecting a symlink.

However this doesn't appear to work consistently on Macs - sometimes the symlink itself gets overwritten, sometimes setting the symlink to "Locked" fixes that and sometimes no.

Case in point.

I like my dotfiles repo to be in its own tidy folder

Ok...I can definately apprecieate a neat and orderly file hieracharcy. However, since the applications will be expecting the Library files to be where they are originally, that folder will just be the same unorganized, badly named list of symlinks instead. So, basically, all for naught.

| improve this answer | |
  • "Unless you're a dev" - I am a dev. – Donentolon Mar 24 at 23:35
  • 1
    Of all the apps you use? – Allan Mar 24 at 23:56
  • Yes, I use open source software when possible and contribute to its development. – Donentolon Mar 25 at 18:22
  • when possible. So, “no” then – Allan Mar 25 at 18:29
0

If anyone is wondering, my current approach is this:

  1. Modify some settings in the app, then quickly do find ~ -mtime -1m 2>/dev/null to see recently changed files and find the one where the app stores configs. (some apps don't actually write the configs until you quit them)
  2. With the app closed, move setting to dotfiles repo: mv ~/Library/Preferences/com.someapp.whatever.blah.blah.plist ~/dotfiles/someapp-config.dat
  3. Symlink from original location: ln -s ~/dotfiles/someapp-config.dat ~/Library/Preferences/com.someapp.whatever.blah.blah.plist
  4. Lock the symlink so the app can't overwrite the symlink (it should still be able to change file contents): chflags nouchg ~/Library/Preferences/com.someapp.whatever.blah.blah.plist (this is the same as right clicking the symlink in Finder, selecting "Get Info..." and then "Locked")
  5. Commit ~/dotfiles/someapp-config.dat to your repository. Usually these files are binary and the diff isn't too useful, so I suggest describing your configuration changes in the commit message. You probably also want to add the symlink and lock commands to a shell script to make deployment on subsequent machines easier (ideally it would be as easy as git clone DOTFILE_URL; ~/dotfiles/install-symlinks.sh).

This seems to work. Without the locking step, many apps would delete the symlink and create a fresh config file. But when it is locked they are forced to follow the symlink and work with the contents of the versioned file.

I had one case where it seemed like the symlink was overwritten despite being locked, but I'm not entirely sure if I actually did lock it. After I tried again and made sure to lock it, I could not reproduce the problem - so maybe I just accidentally failed to lock it the first time. I'll edit the post if I find a reproducible case of the Lock not being sufficient.


Alternatively, it is possible to do it without locking at all (not tested, commands might have minor errors):

  1. Copy entire Preference dir to dotfiles: cp -r ~/Library/Preferences ~/dotfiles/
  2. Replace original one with a symlink: ln -s ~/dotfiles/Preferences ~/Library/Preferences
  3. You probably don't want to indiscriminately version your entire Preferences library, so add it to .gitignore: Preferences/
  4. Use the same recently modified trick to find the relevant config file(s): find ~/dotfiles/Preferences/ -mtime -1m 2>/dev/null
  5. The file won't show up in git status at first because it's ignored but you can still git add com.someapp.whatever.blah.blah.plist (changes in the file will show up in git status after it is added once)

The advantage of this approach is that you don't have to lock any files because even if a program deletes and re-creates the config file, it will still show up in the symlinked directory in your repo. The disadvantage is that you can end up with a lot of files in your local repo - with ordinary git usage and if you ignore them as I describe above, the files won't be committed or pushed to git, but if you ever manually copy the repository (as opposed to git clone like you should be) then you have to keep in mind that you are copying everything.

I don't believe it is necessary to lock the symlink ~/Library/Preferences because that directory shouldn't be getting overwritten (as opposed to its contents).

| improve this answer | |

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .