{"id":18581677,"url":"https://github.com/r2d4/docker-merge","last_synced_at":"2026-03-03T16:02:01.956Z","repository":{"id":49340288,"uuid":"329198448","full_name":"r2d4/docker-merge","owner":"r2d4","description":"Docker images as git repositories, so you can merge them.","archived":false,"fork":false,"pushed_at":"2023-07-14T16:19:00.000Z","size":549,"stargazers_count":35,"open_issues_count":0,"forks_count":5,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-10-16T00:07:27.948Z","etag":null,"topics":["containers","docker","docker-container","git","merge"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/r2d4.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"code-of-conduct.md","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":"2021-01-13T04:58:48.000Z","updated_at":"2024-10-16T23:57:43.000Z","dependencies_parsed_at":"2025-04-10T11:35:52.760Z","dependency_job_id":"ca3d32e0-b6a5-430a-8735-6fa72f529a11","html_url":"https://github.com/r2d4/docker-merge","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/r2d4/docker-merge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r2d4%2Fdocker-merge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r2d4%2Fdocker-merge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r2d4%2Fdocker-merge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r2d4%2Fdocker-merge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/r2d4","download_url":"https://codeload.github.com/r2d4/docker-merge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r2d4%2Fdocker-merge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30051097,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-03T15:26:47.567Z","status":"ssl_error","status_checked_at":"2026-03-03T15:26:17.132Z","response_time":61,"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":["containers","docker","docker-container","git","merge"],"created_at":"2024-11-07T00:06:37.554Z","updated_at":"2026-03-03T16:02:01.926Z","avatar_url":"https://github.com/r2d4.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Docker Merge\n\nAn interesting way to merge two arbitrary docker images.\n\nDocker merge is a CLI utility that provides a proof-of-concept strategy to merge docker images. At its core - it utilizes the branching and merging ideas from git. It provides a conceptual link between Docker Images \u003c=\u003e Git Branches, and Docker Layers \u003c=\u003e Git Commits.\n\nWant to try it out? Go to the [example](#Example).\n\nWant to see how it works? [How it works](#How-it-works).\n\n![Diagram](images/diagram.png)\n\n## Example\n\nWe're going to be merging two docker images - one that outputs fortunes, and another that embeds a message into an ASCII cow.\n\n```\n ______________________________\n/ Five is a sufficiently close \\\n| approximation to infinity.   |\n|                              |\n\\ -- Robert Firth              /\n ------------------------------\n        \\   ^__^\n         \\  (oo)\\_______\n            (__)\\       )\\/\\\n                ||----w |\n                ||     ||\n```\n\n### Installing\n\nWe're going to be building and merging two docker images. To get started, you'll need these two programs installed.\n\n- Docker\n- Git\n\nFirst, install the `dgit` binary\n\n**Linux**\n\n```\ncurl -Lo dgit https://github.com/r2d4/docker-merge/releases/download/v1/dgit-linux-amd64 \u0026\u0026 chmod +x dgit \u0026\u0026 sudo mv dgit /usr/local/bin\n```\n\n**macOS**\n\n```\ncurl -Lo dgit https://github.com/r2d4/docker-merge/releases/download/v1/dgit-darwin-amd64 \u0026\u0026 chmod +x dgit \u0026\u0026 sudo mv dgit /usr/local/bin\n```\n\nClone this example repository to get the example Dockerfiles (or copy them yourself).\n\n```\ngit clone https://github.com/r2d4/docker-merge.git \u0026\u0026 cd docker-merge\n```\n\nNext, we're going to be building two images that we're going to ultimately merge. The first is an alpine-based image that installs fortune, a binary that outputs a random fortune message. The second is another alpine-based image that installs cowsay, a binary that outputs a message in a speech bubble above an ASCII cow.\n\n```\ndocker build -t fortune -f examples/getting-started/Dockerfile_fortune .\ndocker build -t cowsay -f examples/getting-started/Dockerfile_cowsay .\n```\n\nNow let's merge! We're going to tag the merged image as `cow-fortune` using the `-t` flag. The rest of the variadic arguments are images to merge, with the first being the image that \"wins\" in terms of merge conflicts.\n\n```\ndgit merge -t cow-fortune fortune:latest cowsay:latest\n```\n\nFinally, let's test it out!\n\n```\ndocker run -it cow-fortune /bin/sh -c \"fortune | cowsay\"\n```\n\n```\n ___________________________\n\u003c r2d4 sure is a clever one \u003e\n ---------------------------\n        \\   ^__^\n         \\  (oo)\\_______\n            (__)\\       )\\/\\\n                ||----w |\n                ||     ||\n```\n\n## How it works\n\nConceptually, we want to map docker images to git branches, and docker layers to git commits. This allows us to hijack the \"git merge\" strategies to natively \"merge\" docker layers.\n\n### Layers to Commits\n\nFor each image, we unpack the layers sequentially into a git repository. Similar to the docker snapshot mechanisms, we commit each layer. This means that every commit is the full representation of the overlayfs at each layer. Two things are done to make sure this works well. First, a \"super root\", from which all branches originate from, regardless of image. This is to make merges work, even without `--allow-unrelated-histories`. Second, we make sure that git commits are entirely reproducible. The commit SHA includes time of commit and author, so we use consistent metadata to make sure the same layers correspond to the same commits.\n\n### Images to Branches\n\nEach image becomes a branch. We arbitrarily pick the first image to use on the `main` or `master` branch. Every other image becomes its own branch. To finish, we use `git merge` across the branches, with merge strategy `ours` to resolve conflicts.\n\n### Unintended Cool Stuff\n\n- Every commit is the full representation of the overlayfs. This is interesting for debugging. You could also image that this is an alternative for building Docker images imperatively. That means that you can add files via commit rather than a Dockerfile `ADD` or `RUN` command.\n- Native `diff` between layers. Want to understand what has changed from a particular `RUN` command? You can `git diff` between the output commits.\n- Experimenting with merge strategies may yield interesting results for docker images.\n- Abuse GitHub as a free Docker image repository with just a few minor changes. Better yet, add a registry that does this automatically for a specific URL.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr2d4%2Fdocker-merge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fr2d4%2Fdocker-merge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr2d4%2Fdocker-merge/lists"}