{"id":20438491,"url":"https://github.com/vdhamer/git-crypt-demo","last_synced_at":"2026-04-19T06:44:10.973Z","repository":{"id":50682232,"uuid":"519637203","full_name":"vdhamer/Git-Crypt-Demo","owner":"vdhamer","description":"Demo integration of crypt-demo into a Swift Xcode project. The point here is to have code with a secret (encrypted using GitHub) that is also buildable/runnable with reduced functionality when you cannot access the secret.","archived":false,"fork":false,"pushed_at":"2024-05-19T09:43:46.000Z","size":171,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-05T07:24:41.238Z","etag":null,"topics":["encryption","git","git-crypt","git-learning","swift","swift-learning","swiftui"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vdhamer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-30T23:03:11.000Z","updated_at":"2024-05-19T09:43:48.000Z","dependencies_parsed_at":"2025-01-15T19:09:20.374Z","dependency_job_id":"47429f48-9f88-4465-ba80-29ffdeaf7b22","html_url":"https://github.com/vdhamer/Git-Crypt-Demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vdhamer/Git-Crypt-Demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vdhamer%2FGit-Crypt-Demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vdhamer%2FGit-Crypt-Demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vdhamer%2FGit-Crypt-Demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vdhamer%2FGit-Crypt-Demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vdhamer","download_url":"https://codeload.github.com/vdhamer/Git-Crypt-Demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vdhamer%2FGit-Crypt-Demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31997804,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"online","status_checked_at":"2026-04-19T02:00:07.110Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["encryption","git","git-crypt","git-learning","swift","swift-learning","swiftui"],"created_at":"2024-11-15T09:11:54.606Z","updated_at":"2026-04-19T06:44:10.959Z","avatar_url":"https://github.com/vdhamer.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitCryptDemo\n\n## Using `git-crypt` to encrypt files in a public Git repo\n\nThis is an example of integrating [`crypt-demo`](https://github.com/AGWA/git-crypt) into very basic\nSwift/SwiftUI app under Xcode. \nThe aim is to have a Git software repository that contains a tiny file that needs encrypting.\nFurthermore the project should be immediately buildable/runnable —\nregardless of whether the user has access to the required encryption key.\n\nThis \"graceful degradation\" is a feature of `git-crypt`: you can make an app that builds correctly in both states.\nBut this graceful degration also requires that the app's code does its part of the work at runtime:\nif you don't have access to the key, some of the app's functionality needs to be automatically disabled or \ndegraded in whatever way is appropriate for the app. After all, *with* the key, the app runs as intended. \nBut *without* the key something that it would normally need is simply missing, and the app needs to deal with this.\n\n### Requirements and assumptions\n\nThe target requirements are listed here. We will come back to how each is achieved in a later section.\nThe requirements/assumptions:\n1. The app needs to contain a **`Secret`** (e.g., a file containing an API key) that needs to be protected. \n   Anyone with the source code can create and insert their _own_ `Secret`, \n   but they shall not be able to access the `Secret` owned by the original code author.\n2. The app's code is archived in a public repository that contains an *encrypted* copy of the file with the `Secret`.\n3. This implies that there is *another* secret needed so that the app can decrypt the `Secret`. \n   To avoid confusion, we will call that other, second secret the **`Key`**.\n4. The `Key` is *not* shared in the repository (otherwise we would be heading towards even more secrets). \n   This `Key` might be project specific or be reused across a few other projects. The `Key` might be shared via a private communication \n   channel with other project collaborators.\n5. For anyone with access to the `Key`, the app builds and runs as-is, with **full functionality** because access to the `Key` gives access to the `Secret`.\n   This allows the app to be built from the local file system to create a fully functioning app.\n6. But anyone without access to the `Key`, the app builds and runs as-is, but with **reduced functionality**. \n   What \"reduced functionality\" could looks like is entirely up to the app.\n\n### Possible use cases\n\n- A server's API provides sample weather information. \n  But some kind of registration key gives the app more accurate or more recent information.\n- A server's free API provides map data, but at a limited request frequency.\n  A personal license of some sort gives you access to a higher request frequency.\n- A server hosts certain data files that are only accessible if you have some passcode.\n  With the passcode, the app gets some extra functionality.\n- A WordPress website hosts a password-protected page.\n  The password protection can be fetched without user help by passing a secret code (which may differ from the password)\n  as a parameter at the end of the URL. There is a plug-in for this: _Post Password Token_.\n\n### Notes\n\n- Protecting the `Secret` is essential if your repository is public. But it also can act as a safety net\n  when the repository is private: if somebody gets access to the private repo, `Secret` is still safe.\n \n- The demo happens to use Swift, SwiftUI, and Xcode. The approach can be applied to other languages.\n\n- The demo happens to mention GitHub. The principle should work with other Git providers like GitLabs and BitBucket.\n\n- If a user with access to the `Key` generates a binary version of the app for distribution,\n  `Secret` is available somewhere in unencrypted form within the app bundle.\n  So, if you *distribute* that app, `Secret` can be extracted by someone with enough skills and determination.\n  So this approach assumes either *controlled* distribution of the fully functional version, obfuscation of the code,\n  or that the risk is acceptable. This limitation is unavoidable because the fully functional app itself\n  by definition needs access to an unencrypted form of the `Secret`. Example:\n  to get an API to provide certain functionality. So even if you obfuscate `Secret` within the app,\n  there is at least a moment where `Secret` can be accessed in a debugger or, simpler, by snooping network traffic.\n\n- There are undoubtedly alternative approaches that can meet these requirements. For example\n\t- GitHub has a feature to store Secrets that are accessible only to contributors via Actions. \n      In that approach `Secret` is *not* an integral part of the source code, but is also not subject to version-control.\n\t- You might consider using `.gitignore` to simply keep `Secret` out of the repository.\n\t  But this does *not* meet all the requirements.\n          In particular, you will get a compile-time error if an expected file is missing during the build.\n\n### How the 6 requirements are addressed\n\n\u003e 1. the app needs to contain a `Secret` stored in a file within the app bundle.\n\nThis demo app contains a pair of text files named `Unsecret.txt` and `Secret.txt`.\n`Unsecret.txt` contains \"Contents of file Unsecret.txt\" and is not encrypted. \n`Secret.txt` would contain something worth protecting (here it contains the string \"Contents of file Secret.txt\").\nThe app displays \"Contents of file Secret.txt\" if it can, but otherwise degrades to displaying \"Contents of file Unsecret.txt\". :disappointed:\n\n\u003e 2. the app's code repository on GitHub includes an **encrypted** copy of `Secret.txt`.\n\nThe encryption is handled by `git-crypt`, which is configured via an entry in `.gitattributes` that reads\n`Secret.txt filter=git-crypt diff=git-crypt`. If git-crypt is present and is can handle the encryption/decryption,\nthis causes `Secret.txt` to be encrypted when the file is staged for git.\nAnd it gets automatically decrypted when it is pulled from a remote repo.\n\nIf git-crypt is not present or cannot handle the encryption/decryption, the app bundle will contain an encrypted\nfile which the app cannot use. It detects that it is unusable and goes on to some fallback behavior.\n\n\u003e 3. This implies that there is a second secret. Let's call that the `Key`.\n\n`git-crypt`, after initialisation in your project directory, can be asked to export the key via `$ git-crypt export-key \u003cpath\u003e`.\n\nIf you choose `$ git-crypt export-key ../git-crypt-key`, `Key` can be shared across multiple projects in a parent directory.\nAnd you won't lose the key if you delete your project directory and reinstall the app's code from the GitHub repository.\n\n\u003e 4. The `Key` is not shared via the repository.\n\nIf your `Key` is stored *in or below* your project directory, you need to prevent uploading to the repository by\nlisting it in the Git `.gitignore` file.\nIf `Key` is stored in a parent directory, you might want to list it anyway, for safety.\n\n\u003e 5. **with** access to the `Key`, the app builds and runs with **full** functionality\n\nThis is a matter of detecting that the file `Secret.txt` is not encrypted in your local file system and app bundle,\nand using this to do whatever your app needs `Secret` for.\nThe detection can rely on the fact that a file encrypted by `git-crypt` starts with a fixed 10-byte sequence\n(GITCRYPT with a leading and trailing zero byte).\nThe Swift demo app detects this simply by catching if the function call `String(contentsOfFile: filepath)` throws an error.\n\n\u003e 6. **without** access to `Key`, the app builds and runs with **reduced** functionality\n\nThe app needs to implement this custom logic. In this demo it involves using `Unsecret.txt` when `Secret.txt` is unusable.\nAgain, the fact that `Secret` is encrypted is detected here by catching an exception thrown while converting\nthe file content to a Swift String.\n\n### Running the demo\n\nTo get a local copy up and running, use GitHub’s `Open with Xcode` feature, compile and run on a simulator or\nphysical device (iPhone, iPad or Mac). Your local copy of the code will, by default, contain an **encrypted** version\nof `Secret.txt`. And the app bundle (presuming that `Secret.txt` is in your target) contain this `Secret.text` file.\nWhen `Secret.txt` is encrypted, the app automatically uses `Unsecret.txt` instead.\n \n### Tips for integrating this into your app\n\nSetting up something similar from scratch is a bit cumbersome.\n\nArguably because usage of both `.gitignore` and `git-crypt` are relatively error-prone.\nThe complication lies in the fact that it is **very easy** to make a mistake, resulting in the uploading of an\nunencrypted version of `Secret.txt`. And Git makes it extremely difficult to remove all older versions\nof a specific file: Git just don't want you to deal with files, it deals with `commits` instead. So Git works hard\nto make things miserable for anyone who even thinks about (from Git's perspective) corrupting Git's archive of past\ncommits.\n\nAnother complication is that `.gitignore` needs to be set **before** you create the sensitive file.\nYou can't set `.gitignore` and then replace a dummy version of `Secret.txt` by the real thing: \nif you do that, Git ignores that `.gitignore` rule and happily keeps pushing your key to the remote repo.\n\nSo, as general advice:\n\n- Use a **dummy** secret until everything is set up. \n  Then prove to yourself whether that `Secret.txt` is indeed encrypted if you clone the repository without using the key.\n  Then, after enabling encryption, check that you can decrypt the dummy secret using your key.\n  Then `lock` the repo again (you will regret it if you don't).\n  Only insert your real `Secret` into the `Secret.txt` file once you have proven that all this works.\n  If you add your secret earlier while setting all this up, it is almost certain that `Secret` will end up unencrypted\n  in your GitHub repository within some older commit, where it can be read by bots designed specifically for this kind of task.\n- Use the Git command line a lot. Its use can coexist with using the GUI for source management in Xcode:\n\t- Use `git status` (on the command line). Use it a lot to detect general Git issues.\n\t- Use `git-crypt status` (on the command line) even more when making changes to encryption setting or \n      encrypted content. It can actually warn you about leaking unencrypted versions of the file you intended to \n      only publish in encrypted form.\n\n### Stepwise instructions\n\nNormally having access to working source code should be enough to get you going, right?\nUnfortunately, this setup process involves some initialisation via the command line and some files that are often\ndone outside the source code.\n\nSo setting up your own project (in XCode) that uses `git-crypt` can be done as follows.\nRemember that the order of the steps is critical in some places (otherwise you end up with an unencrypted copy of\n`Secret.txt` in the repository or end up publishing your encryption key!):\n\n1.\tCreate an **new project** in XCode. \n\n\tXcode has integrated Git support since 2011, so there is no need to install Git.\n\tYou could have XCode **enable source management** for this project by checking the option\n\t`Source control: ☑︎ Create Git repository on my Mac`. \n\tBut let's do that manually in a moment, so let's uncheck the checkbox.\n\n\tIn about 10 steps, you will need to have an account at GitHub (or a similar service).\n\tThis requires the setup of your authentication with GitHub, and linking Xcode to that GitHub account.\n\tThis can be found in Apple's\n    [source control documentation](https://developer.apple.com/documentation/xcode/configuring-your-xcode-project-to-use-source-control).\n\n2.\tAt this point, your source files are **not version managed** yet.\n\n\tYou can confirm this by running the command line `git status` from a MacOS Terminal or command line window.\n\tThis reports `not a git repository` because there is no `.git` subdirectory in your project's root directory.\n\n3.\t**Enable Git** source control\n\n\tRun `git init` from the Terminal while you are in the root directory of your repository.\n\tThe repo's root directory is the one that contains (at this point) two subdirectories respectively\n\tnamed `GitCryptDemo` and `GitCryptDemo.xcodeproj`.\n\tThe project root directory is also called `GitCryptDemo`,\n\tand will serve to contain everything as the project project grows.\n\tRun 'git status` again to confirm that it worked.\n\n\tActually we need to do a bit more to reach the same point as the checkbox in XCode that we skipped: \n\trun `git add .` (including the period) to put the current contents of the project directory\n\tand its subdirectories under source control.\n\tRun `git status` again to see what files are now being monitored.\n\tThese files are being watched, but haven't been stored in the local git repository get\n    (they haven't been \"committed\"). We will commit these files and more later.\n\n4.  Install the **Homebrew** package manager\n\n\tYou can check if Homebrew is already installed by typing `which brew` in the Terminal.\n\tYou can find Homebrew via GitHub or via [https://brew.sh](https://brew.sh).\n\tHomebrew provides an easy way to install `git-crypt`.\n\n5.\tInstall **git-crypt**\n\n\tThis involves typing `brew install git-crypt` in the Terminal window.\n\tAt the time of this writing, the latest Homebrew version was 0.7.0.\n\t\n\tRun `git-crypt status` to see that the installation was successful.\n\tIt will tell you that none of files being monitored by Git are encrypted so far.\n\n6.\tCreate a basic **.gitignore** file\n\n\tSafety first...\n\n\tBefore generating keys, let's make sure encryption keys never end up in Git or on GitHub.\n\tWe need to add 2 lines to a `.gitignore` text file in your project root directory.\n \tIf the file already exists, use an editor or the editor in Xcode. \n\tIf you need to create the file you could use the following sequence of commands \n\t`cat \u003e.gitignore`,\n\tfollowed by `.git/git-crypt/keys/**`,\n\tand `../git-crypt-key` and finally Control-C.\n\tThis copies two lines of text into the file `.gitignore`.\n\tThe first line covers the default location of `git-crypt` key files.\n\tFor example `myproject/.git/git-crypt/keys/default`.\n\tThe second line covers a name and path where the key might be placed to get it\n\tabove the `myproject` directory, where it can be used by multiple projects.\n\tUse `cat .gitignore` to check the result.\n\n\tIf you run `git status` again now, you will find that the new `.gitignore` file is *not* being tracked.\n\tGit itself wants you to add this file, but we will do that later.\n\n\tIncidentally, if you create files via Xcode's `New file...` menu command,\n\tthey become part of the Xcode project. Which will, in turn, allow Xcode to\n\tautomatically perform `git add` for these project files when you commit all\n\tchanges in the project to Git. \n\tThe setting for this is `Source control: ☑︎ Add and remove files automatically`\n\n7.\tCreating a workable **.gitignore** file\n\t\n\tActually it is good practice to extend `.gitignore` by a set of standard files\n\tused internally by MacOS, XCode and Swift. \n\tYou can generate those lines using the **gitignore.io** or Toptal online \n\t[.gitignore generator](https://www.toptal.com/developers/gitignore/) service.\n\tMost of those lines are for older versions of Xcode, but it avoids cases\n\twhere Git is trying to track Xcode files that save the state of the Xcode user\n\tinterface.\n\tWhich in turn prevents Git from thinking something needs saving, while you were\n\tsure that you didn't modify anything: you didn't change the code, but Xcode update a state file somewhere.\n\n8.\t**Enable `git-crypt`**\n\n\tRun `git-crypt init` to generate a new key,\n\tand `git-crypt export-key ../git-crypt-key` to save it in the parent directory.\n\t\n\tYou can use any file name instead of `git-crypt-key`.\n\tWe gave it a generic name here because it might be used in other projects as well.\n\n\tUse `cat ../git-crypt-key` to view the file.\n\tIt is not really a valid text file, but does contain a text string `GITCRYPTKEY`.\n\n9.\tConfigure **what to encrypt**\n\n\tAn extra file called `.gitattributes` in your project directory will tell git-crypt what to encrypt.\n\tAgain, you might want to use an editor, especially if the file already exists.\n\tAlternatively we can create it from a Terminal window using\n\t`cat \u003e.gitattributes`, followed by\n \t`Secret.txt filter=git-crypt diff=git-crypt` and Control-C.\n\tThis tells Git to use git-crypt to encrypt and decrypt files, and to detect changes in encrypted files (`diff`).\n\n10.\tFix the **path to Homebrew** on MacOS\n\n\tFor newer MacOS with Apple Silicon (M1 and M2 series, etc) use\n\t`echo $PATH` to check that your path contains /opt/homebrew/bin. \n\tThis is relevant because homebrew changed this path with the introduction of the new M-series.\n\n\tBecause I still had problems here, I recommend that, you edit the (existing) `.git/config` file to contain \n\tabsolute path names (I suspect that `filter` and `diff` somehow bypass the path):\n   ~~~\n   [filter \"git-crypt\"]\n      smudge = \\\"/opt/homebrew/bin/git-crypt\\\" smudge\n      clean = \\\"/opt/homebrew/bin/git-crypt\\\" clean\n      required = true\n   [diff \"git-crypt\"]\n      textconv = \\\"/opt/homebrew/bin/git-crypt\\\" diff\n   ~~~\n\nThere must be a better way that solves this for all `git-crypt` projects on MacOS,\nbut this will fix the problem for one individual project.\n\n11.\tCreate **Secret.txt** and **Unsecret.txt**\n\n\tIn your repository's root directory, create `Unsecret.txt` using\n\t`cat \u003eUnsecret.txt`, followed by\n\t`Contents of file Unsecret.txt` and closed by\n\tControl-C.\n\tThis text will not be encrypted.\n\n\tFor `Secret.txt`, it is best to fill it with `Temp secret` instead of an actual secret.\n\tThis is because of the pretty real risk that the file ends up in the repository\n\tin unencrypted form, where it can be very hard to remove.\n\n\tJust \"overwriting\" an unencrypted by an encrypted file with the same file name won't\n\treally work because the older version stays visible in the repository -\n\tfor anyone with a script that scans for such misplaced secrets.\n\tSuch scripts and people do exist.\n\n12.\tIs Git **tracking all the required files**?\n\n\tWith `git status` you can see all files that still need to be committed.\n\tThat includes `Secret.txt`, `Unsecret.txt`, `.gitignore` and `.gitattributes`.\n\tThis is because they were made after `git add .`.\n\n\tYou can add all 4 files now with a new `git add .` command.\n\tRemember that `Secret.txt` **will** be checked into the repository -\n\tbut hopefully only in encrypted form.\n\n13.\tBut will we **encrypt the right files**?\n\n\tNow run `git-crypt status` to check git-crypt's plans for all our files.\n\tIt should show `encrypted: Secret.txt` and `not encrypted: Unsecret.txt`. But...\n\n\tWith `cat Secret.txt` you will discover that the file is still unencrypted in your local directory.\n\tSo \"encrypted\" here should be interpreted as a promise what will happen\n\twhen the file gets copied (\"committed\") into a (local or remote) Git repository.\n\n14.\tHow about **finally** encrypting something?\n\n\tWe first need to commit these 16 or so files to the **local** git repository (in `.git`).\n\tSo use `git commit -m \"Initial commit\"` with -m for the message or documentation of what this commit is.\n\t`git status` will now show that all those files are \"staged\" in your local repo copy.\n\n\tBack in XCode, you can use `File` | `Add files to \"GitCryptDemo.xcodeproj\"...` to add the four new files\n\t(`Secret.txt`, `Unsecret.txt`, `.gitignore` and `.gitattributes`) so they show up in the Xcode project as well.\n\tXCode shows that all source files have been committed. \n\tOnly GitCryptDemo itself may show an M (for **M**odified) in the Project\n\tNavigator. If you really want to know what that is,\n\t`git status` may show a file like `GitCryptDemo.xcodeproj/project.pbxproj` which\n\tis again internal bookkeeping used by Xcode. \n\tWe could ignore it ([here](https://thoughtbot.com/blog/xcode-and-git-bridging-the-gap) is an alternative).\n\n\tAt this point you might actually want to build and run the default app. \n\tOn a Mac it will show a very small, easy to overlook window.\n\tBut you can also run the code on an iOS device where it is shown full screen.\n\n\tIt displays \"Contents of file Unsecret.txt\" with a lower-case \"w\". ????\n\tThat text is neither of the 2 text files, because we are not using them yet.\n\n\tAt this point, we have actually encrypted something (going by `git-crypt status` and\n        the fact that we have done a commit. But it is not really convincing yet.\n\n15.\t**Pushing the commit to GitHub**\n\n\tIn Xcode's Source Code Navigator, go to the Repositories tab.\n\tThere, right-click the topmost item in the tree.\n\tThis gives a menu where you should execute the option\n\t`New \"GitCryptDemo\" Remote...`. \n\tThis means you will be \"pushing\" the content of your local Git repository to a\n\t(just created) remote repository stored under your GitHub account.\n\n\tIf you now navigate (e.g. in a browser) to your account in GitHub,\n\tyou can inspect the committed contents of `Unsecret.txt` and `Secret.txt`.\n\tAnd **NOW** GitHub will show an encrypted version of Secret.txt\n\tand an unencrypted version of `Secret.txt` and all other files.\n\n16.\t**Completing the app**\n\n\tYou can now update the Swift files in the new app to match those in the GitHub\n\tvdHamer/GitCryptDemo repository. That extends the app to use the content of either\n\t`Secret.txt` or `Unsecret.txt` (when the app sees that `Secret.txt` is encrypted).\n\n\tSo within the app you should see \"Temp secret\" displayed,\n\tbecause that is how we left the concent of `Secret.txt` in Step (11).\n\tNow you can edit it to say \"Contents of file Secret.txt\", and commit the change and push it to GitHub.\n\tYou can do this entirely from the `Source Control` menu in Xcode: the encryption is handled automatically.\n\tEssentially Xcode controls git which in turn controls `git-crypt`.\n\n17.\t**Some final testing**\n\n\tTo test what all this looks like if you don't provide the encryption Key, \n\tyou might want to create a new local repository from scratch named `GitCryptDemoClone`, but with the\n\tcontent of the `vdHamer/GitCryptDemo` GitHub repository.\n\tA fast way to do this is to go to [that repository](https://github.com/vdhamer/GitCryptDemo.git),\n\tand click on `Code` and `Open with Xcode`.\n\n\tThen confirm that the file `Secret.txt` is encrypted there by viewing it.\n\tYou should also see that an app built from this repository now displays \"Contents of file Secret.txt\"\n\t(as in the file `Unsecret.txt`). Which confirms that the app decided that file was encrypted.\n\n### Thoughs on \"should it really be this complex?\"\n\nIt took 17 steps to set up everything more or less from scratch.\nWith multiple tricky points - unless you knew most of this already.\n\nAdmittedly, those steps included setting up a GitHub account, linking it to Xcode, installing Brew, \nand installing `git-crypt` using Brew. Which you don't need to do for every project.\nAnd thus may have done years ago.\n\nWe obviously included various steps for checking and learning. \nThese involved lots of command line commands in the Terminal window because Git tends to\nget messed up easily unless you really understand what every command will actually do.\n\nFor example, to give people a mental model of the Git world, there is (kind-of officially sanctioned)\n[Visual Cheatsheet](https://ndpsoftware.com/git-cheatsheet.html#loc=index)\nwhich represents a Git-based environment as 5 boxes between which you copy files and send/collect information:\n\n1. **Stash** (a closet to temporarily hide changes when the going gets rough; not used above)\n2. **Workspace** (the project's directory, used above)\n3. **Index** (bookkeeping files in the .git directory, implicitly used by Git in the above)\n4. the **Local Repository** (a full source controled archive stored in the .git directory, `commits` bring data there)\n5. the **Remote Repository** (GitHub, `pushes` dump data there, but we used Xcode for any `pushing`\n   to handle the required authentication/authorization)\n\nThat 5-box diagram is already hard to understand, so it is animated to show all the main data flow in steps.\nAnd, real world Git usage has more dimensions: you can have multiple `branches` of changes before these are merged. \nAnd you can have as many 'remote' repositories as you want, sometimes containing `forked` rather than `cloned`\ncopies of the code.\n\nArguably Xcode and `git-cryp` add one or more levels to the 5-box model: The Xcode `Project` concept is a lot like the\n(invisible) Git `Index` concept. Both are a registration or directory system used to find and track code and its status.\nYou may thus have files in your directory/localWorkspace that the Xcode Project doesn't know or care about. And files in\nyour Project that Xcode was tracking, but which somehow vanished without Xcode getting notified.\nIn itself a classic example of an abstraction level that can by bypassed, leading to complexity.\n\nAnd Xcode automates some of the interaction with Git, but the Xcode Source Control commands don't cover everything\nand often individual commands map to multiple (configurable in Preferences) Git commands.\nA developer once remarked (likely on StackOverflow, I couldn't find the literal quote):\n\n\u003e  If you want to get help with Git on the Internet, and try to explain your problem in terms of some kind of IDE\n   or graphical shell around Git, you are likely to get no responses from the experts. Every IDE or graphical shell\n   works differently. You will simply have to explain your problem at the generic Git command-line level.\n\nProbably all this points to leaky abstractions. Git is considered a fast, trustworthy, scalable, standard, \nand possibly elegant solution for a way bigger problem than most people handle:\nworld scale distributed collaboration. But it doesn't scale elegantly *downward*\nto handle normal problems using single a readily explainable model.\n\nBy analogy, e-mail protocols also deal with a world scale distributed system that synchronises data\nacross servers and e-mail clients. There too, a single user can use multiple devices to send and view\ne-mails, sometimes across multiple accounts. But the e-mail protocols are designed based on a much more\nexplainable high-level functional model (\"it should arrive eventually\", \"if your device is offline, you\ncan read what your laptop knows about, and prepare a response that will be sent later\", \"you see the same\ninbox across your devices, regardless of what you do\"). In case of Git, it seems the command line\nuser-level commands are the highest available high level model. So you have to express what you need to\ndo in terms of these. Instead of being able to reason about what you are actually trying to do, you have\nto stoop to the level of these commands and try to figure out which set in which order will do what you\nhope to do.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvdhamer%2Fgit-crypt-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvdhamer%2Fgit-crypt-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvdhamer%2Fgit-crypt-demo/lists"}