{"id":15207026,"url":"https://github.com/rhcarvalho/envdiff","last_synced_at":"2026-02-21T16:03:06.515Z","repository":{"id":66869434,"uuid":"54990809","full_name":"rhcarvalho/envdiff","owner":"rhcarvalho","description":"Smart environment diffs","archived":false,"fork":false,"pushed_at":"2016-03-31T17:29:44.000Z","size":16,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-23T07:48:09.700Z","etag":null,"topics":["diff","docker","dockerfile","env","fedora","redhat","scl","shell","software-collections"],"latest_commit_sha":null,"homepage":null,"language":"Go","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/rhcarvalho.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":"2016-03-29T16:13:53.000Z","updated_at":"2019-07-19T18:45:04.000Z","dependencies_parsed_at":"2023-07-27T01:31:46.946Z","dependency_job_id":null,"html_url":"https://github.com/rhcarvalho/envdiff","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rhcarvalho/envdiff","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhcarvalho%2Fenvdiff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhcarvalho%2Fenvdiff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhcarvalho%2Fenvdiff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhcarvalho%2Fenvdiff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rhcarvalho","download_url":"https://codeload.github.com/rhcarvalho/envdiff/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhcarvalho%2Fenvdiff/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29685050,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T15:51:39.154Z","status":"ssl_error","status_checked_at":"2026-02-21T15:49:03.425Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["diff","docker","dockerfile","env","fedora","redhat","scl","shell","software-collections"],"created_at":"2024-09-28T06:06:31.325Z","updated_at":"2026-02-21T16:03:06.496Z","avatar_url":"https://github.com/rhcarvalho.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# envdiff\n\nGenerates smart environment diffs.\n\nThe `envdiff` tool compares two environments, and tries to be smart where it\ncan. For example, it can detect appends or prepends to lists like `PATH`.\n\nGiven two environments `A` and `B`, `envdiff` computes `C` such that:\n\n```\n(export A; export C) == export B\n```\n\nExamples [here](#using).\n\n\n## Installing\n\nYou will need to have the `go` tool [installed](https://golang.org/doc/install),\nthen:\n\n```\ngo get -u github.com/rhcarvalho/envdiff\n```\n\nNow `envdiff` should be in your PATH.\n\n## Using\n\n`envdiff` takes two arguments that should contain a list of newline or null-byte\nseparated environment variables.\n\nExamples:\n\n1. Detecting new variables:\n\n  ```console\n  $ envdiff TERM=xterm $'TERM=xterm\\nFOO=bar'\n  FOO=bar\n  ```\n\n2. Detecting removed variables:\n\n  ```console\n  $ envdiff $'TERM=xterm\\nFOO=bar' TERM=xterm\n  FOO=\n  ```\n\n3. Detecting changing of a list:\n\n  ```console\n  $ envdiff PATH=/bin:/sbin PATH=/usr/bin/:/usr/sbin:/bin:/sbin\n  PATH=/usr/bin/:/usr/sbin:$PATH\n  ```\n\n\n## How to reverse-engineer a Software Collection for Docker images\n\nBy detecting environment changes introduced by enabling certain [Software\nCollections](https://www.softwarecollections.org) (SCL) and writing a Dockerfile\nENV instruction that has the same effect, one can create Docker images that have\nthe given collections enabled by default.\n\nFor example, if you install a Ruby collection in a CentOS image, you might as\nwell want to have the `ruby` binary in your PATH. A user of your image need not\nto know about SCL or have to do any extra steps to be able to run a line like:\n\n```\ndocker run --rm scl-enabled-ruby-image ruby -e 'puts \"Hello World!\"'\n```\n\nGreat, how do I do that with `envdiff`? There's really only **one** required\nstep!\n\n1. Point `envdiff` at your target image:\n\n  ```console\n  $ envdiff -o docker scl openshift/ruby-20-centos7\n  # -- generated by https://github.com/rhcarvalho/envdiff, do not edit manually --\n  # The ENV instruction below is equivalent to:\n  #   scl enable nodejs010 ror40 ruby200 v8314\n  ENV MANPATH=/opt/rh/v8314/root/usr/share/man:/opt/rh/ruby200/root/usr/share/man:/opt/rh/ror40/root/usr/share/man:/opt/rh/v8314/root/usr/share/man:/opt/rh/nodejs010/root/usr/share/man: \\\n      LIBRARY_PATH=/opt/rh/v8314/root/usr/lib64:/opt/rh/v8314/root/usr/lib64 \\\n      X_SCLS=nodejs010 ror40 v8314  \\\n      LD_LIBRARY_PATH=/opt/rh/v8314/root/usr/lib64:/opt/rh/ruby200/root/usr/lib64:/opt/rh/ror40/root/usr/lib64:/opt/rh/v8314/root/usr/lib64:/opt/rh/nodejs010/root/usr/lib64 \\\n      CPATH=/opt/rh/v8314/root/usr/include:/opt/rh/v8314/root/usr/include \\\n      PATH=/opt/rh/v8314/root/usr/bin:/opt/rh/ruby200/root/usr/bin:/opt/rh/ror40/root/usr/bin:/opt/rh/v8314/root/usr/bin:/opt/rh/nodejs010/root/usr/bin:/usr/local/bin:/usr/bin \\\n      PYTHONPATH=/opt/rh/v8314/root/usr/lib/python2.7/site-packages:/opt/rh/v8314/root/usr/lib/python2.7/site-packages:/opt/rh/nodejs010/root/usr/lib/python2.7/site-packages \\\n      GEM_PATH=/opt/rh/ror40/root/usr/share/gems:/opt/app-root/src/.gem/ruby:/opt/rh/ruby200/root/usr/share/gems:/opt/rh/ruby200/root/usr/local/share/gems \\\n      PKG_CONFIG_PATH=/opt/rh/v8314/root/usr/lib64/pkgconfig:/opt/rh/ruby200/root/usr/lib64/pkgconfig:/opt/rh/ror40/root/usr/lib64/pkgconfig:/opt/rh/v8314/root/usr/lib64/pkgconfig\n  # -- end of generated instruction --\n  ```\n\n2. (Optional) You may want to redirect the output straight into a Dockerfile:\n\n  ```\n  envdiff -o docker scl openshift/ruby-20-centos7 \u003e\u003e Dockerfile\n  ```\n\nIf you want to print the environment in shell format, omit the `-o docker` flag:\n\n```console\n$ envdiff scl openshift/python-34-centos7\n# scl enable rh-python34\nMANPATH=/opt/rh/rh-python34/root/usr/share/man:\nX_SCLS=rh-python34\nLD_LIBRARY_PATH=/opt/rh/rh-python34/root/usr/lib64\nPATH=/opt/rh/rh-python34/root/usr/bin:/usr/local/bin:/usr/bin\nXDG_DATA_DIRS=/opt/rh/rh-python34/root/usr/share\nPKG_CONFIG_PATH=/opt/rh/rh-python34/root/usr/lib64/pkgconfig\n```\n\n### How does the scl mode works?\n\nWhat is `envdiff` doing to generate an environment that transforms an initial\nenvironment into one with collections enabled?  \nYou can go read the code, it's all in the `scl.go` file, or follow along.\n\nFirst, we need to discover what collections are installed. This can be\naccomplished with `scl --list` in a container.\n\nSecond, we need two environments: one without any collections enabled, and\nanother one will all collections enabled.\n\nTo get a clean environment, we run `bash -c env` in a temporary container. We\nwrap the call to `env` in a Bash shell to be closer to what we get by enabling\ncollections. To make sure that the environment is clean no matter what is in the\nimage, we unset all environment variables set in the image when creating a\ncontainer.\n\nTo get the environment with all collections enabled, it is `scl enable\ncollection1 collection2 ... env`. In other words, we run `env` to dump the\nenvironment with all collections from the first step being enabled. Since `scl`\nhas a shebang that points to `/bin/bash`, this time we don't wrap the `env` call\nlike in the previous step.\n\nThe last step is to do what `envdiff` is made to do: compare two environments.\nProducing output as a Dockerfile ENV instruction makes it convenient to modify\nexisting Dockerfiles to permanently enable collections.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhcarvalho%2Fenvdiff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frhcarvalho%2Fenvdiff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhcarvalho%2Fenvdiff/lists"}