{"id":17044769,"url":"https://github.com/keredson/ygit","last_synced_at":"2025-07-27T17:05:25.604Z","repository":{"id":148518874,"uuid":"620533964","full_name":"keredson/ygit","owner":"keredson","description":"A tiny (yocto) git client for MicroPython.","archived":false,"fork":false,"pushed_at":"2025-02-26T05:09:11.000Z","size":383,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-27T17:05:01.167Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/keredson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2023-03-28T21:51:22.000Z","updated_at":"2025-02-26T05:09:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"2e763f85-9a18-4b3e-bdc3-00b7baaf8c7e","html_url":"https://github.com/keredson/ygit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/keredson/ygit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keredson%2Fygit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keredson%2Fygit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keredson%2Fygit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keredson%2Fygit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/keredson","download_url":"https://codeload.github.com/keredson/ygit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keredson%2Fygit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267392538,"owners_count":24079918,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-27T02:00:11.917Z","response_time":82,"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":[],"created_at":"2024-10-14T09:35:28.147Z","updated_at":"2025-07-27T17:05:25.596Z","avatar_url":"https://github.com/keredson.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"![header](misc/header.png)\n\n# ygit\nA tiny (yocto) git client for [MicroPython](https://micropython.org/) microcontrollers / other memory-constrained environments (\u003c100k)\nlike the [$6](https://www.amazon.com/Teyleten-Robot-ESP-WROOM-32-Development-Microcontroller/dp/B08246MCL5) \n[ESP32](https://en.wikipedia.org/wiki/ESP32).  It speaks to git HTTP/HTTPS servers using the ubiquitous \n[smart client protocol](https://www.git-scm.com/docs/http-protocol#_smart_clients).  \n\nIt supports branches/tags, shallow clones and sparse checkouts (ie: only checking out a sub-directory of a larger project).\n\nI use it to remotely deploy/update code over low-bandwidth connections.\n\n\n## Install\n```bash\n$ wget https://raw.githubusercontent.com/keredson/ygit/main/ygit.py\n$ mpy-cross ygit.py\n$ ampy -p /dev/ttyUSB0 put ygit.mpy\n```\n\n## Get Started\nTo clone a repo, run:\n```python\n\u003e\u003e\u003e repo = ygit.clone('https://github.com/turfptax/ugit_test.git')\n```\nIf you don't want to clone into the root directory of your device, pass a target directory as a second argument.  This will produce a shallow clone (at `HEAD`) by default.  It will not delete any files in the target directory, but it will overwrite them if conflicting.  The normal git files you'd expect (`config`, `*.pack`, `IDX`) will be in `.ygit`.  You only need to run this once.\n\nTo update:\n```python\n\u003e\u003e\u003e repo.pull()\n```\nWhich is the same as:\n```python\n\u003e\u003e\u003e repo.fetch()\n\u003e\u003e\u003e repo.checkout()\n```\nThese are incremental operations.  It will only download git objects you don't already have, and only update files when their SHA1 values don't match.\n\n\n## API\n\n```python\n# make a new clone\nrepo = ygit.clone(repo, directory='.', shallow=True, cone=None, \n                  quiet=False, ref='HEAD', username=None, password=None)\n\n# control an already cloned repository\nrepo = ygit.Repo(directory='.')\n\n# control\nrepo.checkout(ref='HEAD')\nrepo.pull(shallow=True, quiet=False, ref='HEAD')\nrepo.fetch(shallow=True, quiet=False, ref='HEAD')\nrepo.status(ref='HEAD')\nrepo.tags()\nrepo.branches()\nrepo.pulls()\nrepo.update_authentication(username, password)\nrepo.log()\n```\nA `ref` is one of: \n- `HEAD`\n- a commit (ex: `7b36b4cb1616694d8562f3adea656a709b9831d9`)\n- a branch / tag / pull\n\nRead the [full documentation](https://ygit.readthedocs.io/en/latest/api.html).\n\n\n## Design\n\n### Shallow Cloning\nBy default clones are [shallow](https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/) to\nsave space.  If you try to checkout an unknown ref, `ygit` will fetch a new packfile from the original server.\n\n\n### Subdirectory Cloning\nUsually I don't want to clone an entire project onto my ESP32.  The python I want on the device is in a subdirectory of a larger project.  The `cone` argument will take a path, and only files in that directory will be checked out (as if it were the top level).\n\n**TODO:** Do a blob filter to only fetch objects we intend to check out.\n\n\n### Authentication\nSupply a username/password to `clone()`.  The credentials will be stored on the device, AES encrypted with the machine\nid as the key.  For GitHub, use your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)\nas the password (just like w/ regular `git`).\n\n\n## Tests\n- *Prereq:* Run `nginx -c \"$(pwd)/misc/test_nginx.conf\" -e stderr` in the background for the local tests.\n- `pytest test_localhost.py` (runs local tests) \n- `pytest test_gh.py` (runs github tests)\n- `pytest test_micropython.py` (**WARNING:** will wipe all files except `boot.py` from your MicroPython device at `/dev/ttyUSB0`.)\n\nAs a convenience, running `python test_micropython.py` (note `python` instead of `pytest`) will run only the reset device code.  I \ntypically run `python test_micropython.py \u0026\u0026 picocom /dev/ttyUSB0 -b 115200` when making a change.\n\n## Example Run\n```\n$ picocom /dev/ttyUSB0 -b 115200\n\nMicroPython v1.19.1 on 2022-06-18; ESP32 module with ESP32\nType \"help()\" for more information.\n\n\u003e\u003e\u003e import ygit\n\u003e\u003e\u003e repo = ygit.clone('https://github.com/keredson/ygit.git','ygit')\ncloning https://github.com/keredson/ygit.git into ygit @ HEAD\nfetching: https://github.com/keredson/ygit.git @ HEAD\nfetching commit: bc0f8c042d06f3c78be2066af11419357d1b6e0e\nEnumerating objects: 26, done.\nCounting objects:   3% (1/26)\n[...]\nCounting objects: 100% (26/26), done.\nCompressing objects:   8% (2/24)\n[...]\nCompressing objects: 100% (24/24), done.\n\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\nTotal 26 (delta 0), reused 15 (delta 0), pack-reused 0\n##########################\nchecking out bc0f8c042d06f3c78be2066af11419357d1b6e0e\nwriting: ygit/.gitignore (BLOB)\nwriting: ygit/.readthedocs.yml (BLOB)\nwriting: ygit/LICENSE (BLOB)\nwriting: ygit/README.md (BLOB)\nwriting: ygit/deploy.sh (BLOB)\nwriting: ygit/pyproject.toml (BLOB)\nwriting: ygit/requirements.txt (BLOB)\nwriting: ygit/setup.py (BLOB)\nwriting: ygit/test_gh.py (BLOB)\nwriting: ygit/test_localhost.py (BLOB)\nwriting: ygit/test_micropython.py (BLOB)\nwriting: ygit/ygit.py (BLOB)\nwriting: ygit/docs/Makefile (BLOB)\nwriting: ygit/docs/api.rst (BLOB)\nwriting: ygit/docs/conf.py (BLOB)\nwriting: ygit/docs/index.rst (BLOB)\nwriting: ygit/docs/make.bat (BLOB)\nwriting: ygit/docs/usage.rst (BLOB)\nwriting: ygit/docs/source/api.rst (BLOB)\nwriting: ygit/docs/source/conf.py (BLOB)\nwriting: ygit/docs/source/index.rst (BLOB)\nwriting: ygit/docs/source/usage.rst (BLOB)\nwriting: ygit/misc/header.png (BLOB)\nwriting: ygit/misc/header.xcf (BLOB)\nwriting: ygit/misc/test_nginx.conf (BLOB)\n\u003e\u003e\u003e \n\u003e\u003e\u003e repo.pull()\nfetching: https://github.com/keredson/ygit.git @ HEAD\nfetching commit: bc0f8c042d06f3c78be2066af11419357d1b6e0e\nup to date!\n\n```\n\n## Known Issues\nEvery object in a git repo is stored as a zlib compressed stream.  Decompressing requires a 32k buffer, \na serious contraint on a device w/ only ~100k available RAM.  `ygit` only ever creates one at a time, but\nsometimes the MicroPython garbage collector will get overwhelmed, or memory get's \nfragmented, and you'll get a `MemoryError`.  If you experience this, I've written a \n[fork](https://github.com/keredson/micropython) (and [PR](https://github.com/micropython/micropython/pull/11183))\nthat lets you reuse the same buffer for all objects without bothering the GC.  `ygit` will use this\nautomatically if available.\n\nI've mostly seen this on repos large enough to max out flash storage or when pulling `shallow=False`, so \nit's unlikely to hit most users, but wanted to mention.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeredson%2Fygit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkeredson%2Fygit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeredson%2Fygit/lists"}