{"id":28540108,"url":"https://github.com/virviil/oci2git","last_synced_at":"2026-03-15T22:22:18.443Z","repository":{"id":291257531,"uuid":"977113202","full_name":"Virviil/oci2git","owner":"Virviil","description":"Introspecting Docker images as easy as using Git","archived":false,"fork":false,"pushed_at":"2025-12-22T10:08:04.000Z","size":12668,"stargazers_count":384,"open_issues_count":13,"forks_count":14,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-01-19T22:38:14.700Z","etag":null,"topics":["docker","git","hacktoberfest","oci"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Virviil.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-03T13:03:21.000Z","updated_at":"2026-01-13T11:20:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"98048319-c338-4765-90cf-7723c6d630f7","html_url":"https://github.com/Virviil/oci2git","commit_stats":null,"previous_names":["virviil/oci2git"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/Virviil/oci2git","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Virviil%2Foci2git","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Virviil%2Foci2git/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Virviil%2Foci2git/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Virviil%2Foci2git/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Virviil","download_url":"https://codeload.github.com/Virviil/oci2git/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Virviil%2Foci2git/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28633757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"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":["docker","git","hacktoberfest","oci"],"created_at":"2025-06-09T19:08:16.502Z","updated_at":"2026-03-15T22:22:18.416Z","avatar_url":"https://github.com/Virviil.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003cdiv align=\"right\"\u003e\n  \u003cdetails\u003e\n    \u003csummary \u003e🌐 Language\u003c/summary\u003e\n    \u003cdiv\u003e\n      \u003cdiv align=\"center\"\u003e\n        \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=en\"\u003eEnglish\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=zh-CN\"\u003e简体中文\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=zh-TW\"\u003e繁體中文\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=ja\"\u003e日本語\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=ko\"\u003e한국어\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=hi\"\u003eहिन्दी\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=th\"\u003eไทย\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=fr\"\u003eFrançais\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=de\"\u003eDeutsch\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=es\"\u003eEspañol\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=it\"\u003eItaliano\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=ru\"\u003eРусский\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=pt\"\u003ePortuguês\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=nl\"\u003eNederlands\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=pl\"\u003ePolski\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=ar\"\u003eالعربية\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=fa\"\u003eفارسی\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=tr\"\u003eTürkçe\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=vi\"\u003eTiếng Việt\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=id\"\u003eBahasa Indonesia\u003c/a\u003e\n        | \u003ca href=\"https://openaitx.github.io/view.html?user=Virviil\u0026project=oci2git\u0026lang=as\"\u003eঅসমীয়া\u003c/a\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/details\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"assets/logo.png\" width=\"140px\" /\u003e\n\n# OCI2Git\n\n[![Documentation](https://docs.rs/oci2git/badge.svg)][documentation]\n[![Crates.io](https://img.shields.io/crates/v/oci2git.svg)](https://crates.io/crates/oci2git)\n[![License](https://img.shields.io/crates/l/oci2git.svg)](https://github.com/Virviil/oci2git/blob/master/LICENSE)\n[![Downloads](https://img.shields.io/crates/d/oci2git.svg)](https://crates.io/crates/oci2git)\n\n[//]: # (mock for future test.yaml)\n[//]: # ([![Test Status]\u0026#40;https://img.shields.io/github/actions/workflow/status/Virviil/oci2git/rust.yml?branch=master\u0026event=push\u0026label=Test\u0026#41;]\u0026#40;https://github.com/Virviil/oci2git/actions\u0026#41;)\n\n\u003cdiv align=\"left\"\u003e \u003c/div\u003e  \n\u003c/div\u003e\n\nA Rust application that converts container images (Docker, etc.) to Git repositories, and generates filesystem bill of materials (fsbom) in YAML. Each container layer is represented as a Git commit, preserving the history and structure of the original image.\n\n![Demo of OCI2Git converting the nginx image](./assets/nginx.gif)\n\n## Features\n\n- Analyze Docker images and extract layer information\n- Create a Git repository where each image layer is represented as a commit\n- Generate a YAML filesystem bill of materials (fsbom) with per-layer file listings\n- Support for empty layers (ENV, WORKDIR, etc.) as empty commits\n- Complete metadata extraction to Markdown format\n- Extensible architecture for supporting different container engines\n\n## Use Cases\n\n### Layer Diffing\nWhen troubleshooting container issues, you can use Git's powerful diffing capabilities to identify exactly what changed between any two layers. By running `git diff` between commits, engineers can see precisely which files were added, modified, or deleted, making it much easier to understand the impact of each Dockerfile instruction and locate problematic changes.\n![Example for layer diff](./assets/layer-diff.png)\n\n### Origin Tracking\nUsing `git blame`, developers can quickly determine which layer introduced a specific file or line of code. This is particularly valuable when diagnosing issues with configuration files or dependencies. Instead of manually inspecting each layer, you can immediately trace the origin of any file back to its source layer and corresponding Dockerfile instruction.\n\n### File Lifecycle Tracking\nOCI2Git enables you to follow a specific file's journey throughout the container image's history. You can observe when a file was initially created, how it was modified across layers, and if/when it was eventually removed. This comprehensive view helps understand file evolution without having to manually track changes across potentially dozens of layers.\n\nTo track the history of a file in your container image — including when it first appeared, was changed, or deleted — you can use these Git commands after conversion:\n\n```bash\n# Full history of a file (including renames)\ngit log --follow -- /rootfs/my/file/path\n\n# First appearance (i.e. creation) - see which layer introduced the file\ngit log --diff-filter=A -- /rootfs/my/file/path\n\n# All changes made to the file (with diffs)\ngit log -p --follow -- /rootfs/my/file/path\n\n# When the file was deleted\ngit log --diff-filter=D -- /rootfs/my/file/path\n\n# Show short commit info (concise layer history)\ngit log --follow --oneline -- /rootfs/my/file/path\n```\n\nThese commands make it simple to trace any file's complete history across container layers without the complexity of manually extracting and comparing layer tarballs.\n\n### Multi-Layer Analysis\nSometimes the most insightful comparisons come from examining changes across multiple non-consecutive layers. With OCI2Git, you can use Git's comparison tools to analyze how components evolved over multiple build stages, identifying patterns that might be invisible when looking only at adjacent layers.\n\n### Layer Exploration\nBy using `git checkout` to move to any specific commit, you can examine the container filesystem exactly as it existed at that layer. This allows developers to inspect the precise state of files and directories at any point in the image's creation process, providing invaluable context when debugging or examining container behavior.\n![Checkout to previous commit](./assets/checkout.png)\n\n### Multi-Image Analysis\n\nWhen working with multiple container images that share common ancestry, OCI2Git intelligently creates branches only when the images actually diverge. This allows you to analyze multiple related images in a single repository while preserving their common history.\n\n```bash\n# Convert first image to create the base repository\noci2git postgres:16.9-alpine3.21 -o alp\n\n# Convert second image to the same output folder\noci2git nginx:1.28.0-alpine-slim -o alp\n```\n\nOCI2Git automatically detects shared layers between images and creates a branching structure that reflects their common base. The Git history will show:\n- A common trunk containing all shared layers\n- Separate branches that diverge only when the images actually differ\n- Clear visualization of where images share common ancestry vs. where they become unique\n- Smart duplicate handling: if the exact same image is processed twice, the algorithm detects this before the final metadata commit and skips creating a duplicate branch\n\nThis approach is particularly valuable for:\n- **Image Family Analysis**: Understanding how different variants of an image (different versions, architectures, or configurations) relate to each other\n- **Base Image Impact**: Seeing exactly how changes to a base image affect multiple derived images\n- **Optimization Opportunities**: Identifying shared components that could be better leveraged across image variants\n\n![Multi-image repository structure showing shared base and diverging branches](./assets/multiimage.png)\n\n### Additional Use Cases\n\n- **Security Auditing**: Identify exactly when vulnerable packages or configurations were introduced and trace them back to specific build instructions.\n- **Image Optimization**: Analyze layer structures to find redundant operations or large files that could be consolidated, helping to reduce image size.\n- **Dependency Management**: Monitor when dependencies were added, upgraded, or removed across the image history.\n- **Build Process Improvement**: Examine layer composition to optimize Dockerfile instructions for better caching and smaller image size.\n- **Cross-Image Comparison**: Convert multiple related images to Git repositories and use Git's comparison tools to analyze their differences and commonalities.\n\n## Installation\n\n### Package Managers\n\n#### macOS / Linux (Homebrew)\n\n```bash\nbrew tap virviil/oci2git\nbrew install oci2git\n```\n\n#### Debian / Ubuntu\n\nDownload and install the .deb package from the [latest release](https://github.com/virviil/oci2git/releases/latest):\n\n```bash\n# For amd64 (x86_64)\nwget https://github.com/virviil/oci2git/releases/latest/download/oci2git_VERSION_amd64.deb\nsudo dpkg -i oci2git_VERSION_amd64.deb\n\n# For arm64\nwget https://github.com/virviil/oci2git/releases/latest/download/oci2git_VERSION_arm64.deb\nsudo dpkg -i oci2git_VERSION_arm64.deb\n```\n\n#### Arch Linux (AUR)\n\n```bash\n# Using yay\nyay -S oci2git-bin\n\n# Using paru\nparu -S oci2git-bin\n\n# Manual installation\ngit clone https://aur.archlinux.org/oci2git-bin.git\ncd oci2git-bin\nmakepkg -si\n```\n\n### Pre-built Binaries\n\nDownload the appropriate binary for your platform from the [latest release](https://github.com/virviil/oci2git/releases/latest):\n\n```bash\n# Linux x86_64\nwget https://github.com/virviil/oci2git/releases/latest/download/oci2git-linux-x86_64.tar.gz\ntar xzf oci2git-linux-x86_64.tar.gz\nsudo mv oci2git-linux-x86_64 /usr/local/bin/oci2git\nchmod +x /usr/local/bin/oci2git\n\n# macOS (Apple Silicon)\nwget https://github.com/virviil/oci2git/releases/latest/download/oci2git-darwin-aarch64.tar.gz\ntar xzf oci2git-darwin-aarch64.tar.gz\nsudo mv oci2git-darwin-aarch64 /usr/local/bin/oci2git\nchmod +x /usr/local/bin/oci2git\n```\n\n### From Crates.io\n\n```bash\ncargo install oci2git\n```\n\n### From Source\n\n```bash\n# Clone the repository\ngit clone https://github.com/virviil/oci2git.git\ncd oci2git\n\n# Install locally\ncargo install --path .\n```\n\n## Usage\n\n```\noci2git [OPTIONS] \u003cIMAGE\u003e\noci2git convert [OPTIONS] \u003cIMAGE\u003e\noci2git fsbom [OPTIONS] \u003cIMAGE\u003e\n```\n\n### `convert` — OCI image → Git repository\n\n```bash\noci2git convert [OPTIONS] \u003cIMAGE\u003e\n# or simply:\noci2git \u003cIMAGE\u003e\n```\n\nOptions:\n  `-o, --output \u003cOUTPUT\u003e`  Output directory for Git repository [default: ./container_repo]\n  `-e, --engine \u003cENGINE\u003e`  Container engine to use (docker, nerdctl, tar) [default: docker]\n  `-v, --verbose`          Verbose mode (-v for info, -vv for debug, -vvv for trace)\n\n### `fsbom` — Filesystem bill of materials\n\n```bash\noci2git fsbom [OPTIONS] \u003cIMAGE\u003e\n```\n\nOptions:\n  `-o, --output \u003cOUTPUT\u003e`  Output path for the YAML BOM file [default: ./fsbom.yml]\n  `-e, --engine \u003cENGINE\u003e`  Container engine to use (docker, nerdctl, tar) [default: docker]\n  `-v, --verbose`          Verbose mode (-v for info, -vv for debug, -vvv for trace)\n\nEnvironment Variables:\n  `TMPDIR`  Set this environment variable to change the default location used for intermediate data processing. This is platform-dependent (e.g., `TMPDIR` on Unix/macOS, `TEMP` or `TMP` on Windows).\n\n## Examples\n\n### Convert\n\nUsing Docker engine (default):\n```bash\noci2git ubuntu:latest\n# or explicitly:\noci2git convert ubuntu:latest -o ./ubuntu-repo\n```\n\nUsing an already downloaded image tarball:\n```bash\noci2git convert -e tar -o ./ubuntu-repo /path/to/ubuntu-latest.tar\n```\n\nThe tar engine expects a valid OCI format tarball, which is typically created with `docker save`:\n```bash\n# Create a tarball from a local Docker image\ndocker save -o ubuntu-latest.tar ubuntu:latest\n\n# Convert the tarball to a Git repository\noci2git convert -e tar -o ./ubuntu-repo ubuntu-latest.tar\n```\n\nThis will create a Git repository in `./ubuntu-repo` containing:\n- `Image.md` - Complete metadata about the image in Markdown format\n- `rootfs/` - The filesystem content from the container\n\nThe Git history reflects the container's layer history:\n- The first commit contains only the `Image.md` file with full metadata\n- Each subsequent commit represents a layer from the original image\n- Commits include the Dockerfile command as the commit message\n\n### Filesystem Bill of Materials (fsbom)\n\nGenerate a YAML listing of every file introduced or modified per layer:\n```bash\noci2git fsbom ubuntu:latest -o ubuntu.yml\n```\n\nUsing a tarball:\n```bash\noci2git fsbom -e tar image.tar -o image-bom.yml\n```\n\nThe output YAML lists every layer with its entries tagged by type (`file`, `hardlink`, `symlink`, `directory`) and status (`n:uid:gid` for new, `m:uid:gid` for modified). Deleted files (OCI whiteouts) are excluded.\n\n```yaml\nlayers:\n  - index: 0\n    command: \"ADD rootfs.tar.gz / # buildkit\"\n    digest: \"sha256:45f3ea58...\"\n    entries:\n      - type: file\n        path: \"bin/busybox\"\n        size: 919304\n        mode: 493\n        stat: \"n:0:0\"\n      - type: hardlink\n        path: \"bin/sh\"\n        target: \"bin/busybox\"\n        stat: \"n:0:0\"\n      - type: symlink\n        path: \"lib64\"\n        target: \"lib\"\n        stat: \"n:0:0\"\n  - index: 1\n    command: \"RUN apk add --no-cache curl\"\n    digest: \"sha256:...\"\n    entries:\n      - type: file\n        path: \"usr/bin/curl\"\n        size: 204800\n        mode: 493\n        stat: \"n:0:0\"\n      - type: file\n        path: \"etc/apk/world\"\n        size: 32\n        mode: 420\n        stat: \"m:0:0\"\n```\n\n## Repository Structure\n\n```\nrepository/\n├── .git/\n├── Image.md     # Complete image metadata\n└── rootfs/      # Filesystem content from the container\n```\n\n\n## Requirements\n\n- Rust 2021 edition\n- Docker CLI (for Docker engine support)\n- Git\n\n## License\n\nMIT\n\n[documentation]: https://docs.rs/oci2git/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvirviil%2Foci2git","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvirviil%2Foci2git","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvirviil%2Foci2git/lists"}