{"id":20836716,"url":"https://github.com/filbranden/git-rpmbuild","last_synced_at":"2026-04-28T16:33:37.500Z","repository":{"id":83424837,"uuid":"208561747","full_name":"filbranden/git-rpmbuild","owner":"filbranden","description":"Build RPM packages from Development Trees","archived":false,"fork":false,"pushed_at":"2019-09-15T08:06:58.000Z","size":16,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-12T09:35:06.345Z","etag":null,"topics":["development-workflow","fedora","git","rpm-packages","rpmbuild"],"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-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/filbranden.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}},"created_at":"2019-09-15T08:06:27.000Z","updated_at":"2020-10-12T09:02:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"0613d519-9c16-4ffc-a39c-c0e1b54a6bdd","html_url":"https://github.com/filbranden/git-rpmbuild","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/filbranden/git-rpmbuild","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filbranden%2Fgit-rpmbuild","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filbranden%2Fgit-rpmbuild/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filbranden%2Fgit-rpmbuild/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filbranden%2Fgit-rpmbuild/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/filbranden","download_url":"https://codeload.github.com/filbranden/git-rpmbuild/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filbranden%2Fgit-rpmbuild/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32390017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: 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":["development-workflow","fedora","git","rpm-packages","rpmbuild"],"created_at":"2024-11-18T00:31:40.118Z","updated_at":"2026-04-28T16:33:37.471Z","avatar_url":"https://github.com/filbranden.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# git-rpmbuild\n\nBuild RPM packages from Development Trees.\n\nUse RPMs to deploy and test development versions of your package, during your\ndevelopment cycle. Quickly build RPM packages, using incremental builds from\nyour worktree. Use RPM to install the packages locally and easily rollback by\ndowngrading back to the distro packages.\n\n## Using git-rpmbuild for development\n\nIn order to use git-rpmbuild, simply check out a development tree from the\nupstream git repository. Create and check out your own development branches, add\nyour own commits and maybe even keep uncommitted changes on your worktree.\n\nThen build RPM packages for your package using:\n\n```\n$ git rpmbuild\n```\n\nThis will then detect which package you're building and download the RPM\nspecfile from Fedora, and use that specfile to build RPM packages using the\ndevelopment sources from your worktree.\n\nThe build is incremental, so it's typically pretty quick if you're only\nmodifying a handful of files in the project in between each build, since only\nthose files and the targets that depend on them need to be rebuilt each time.\n\nOnce the RPMs are built, you can install them using:\n\n```\n$ sudo rpm -Fvh ~/rpmbuild/RPMS/*/mypackage-*.rpm\n```\n\nThe RPM \"Release:\" part of the version is used both to prefer latest versions on\ninstalls (making it easy to accumulate builds around) and to keep enough\ninformation on each package to track it back to the sources.\n\nThe \"Release:\" field will include a full timestamp (`YYYYMMDDHHMMSS`), so that\nmore recent builds will be considered newer. The `rpm -F` command will prefer\nthose, so when you use it on an `RPMS/` directory with many builds, the latest\none will be installed by it.\n\nFurthermore, \"Release:\" will include the output of `git describe`, which\ntypically includes the closest tag (which is typically used for the upstream\nversion), plus the name of the local branch checked out (so if you're using\nfeature branches, you can recognize which of them was used in a specific set of\npackages you built.)\n\nIf you'd like to rollback an install, back to the packages shipped by your\ndistribution, you can then use the following command:\n\n```\n$ sudo dnf downgrade mypackage\n```\n\nThe 14-digit timestamp also makes it likely that the `git rpmbuild` packages\nwill have a higher version than the distribution packages, so normally `dnf` or\n`yum` will not replace them, even if the distribution has released newer\nreleases of that same package. (It is possible that the distro packages will\nbecome newer if they release a new major version, though.)\n\n## Advantages of git-rpmbuild over direct local install\n\nThere are many advantages of using `git rpmbuild` over installing binaries\nlocally using `sudo ninja install` or `sudo make install`.\n\nSome of the advantages of this approach are:\n\n- **Same build configuration as the distro:** Since the build is using the\n  instructions from the RPM specfile, the `./configure` or `meson` invocation\n  will incorporate all the options used in the build of the package for your\n  distribution, such as the typical directories (prefix, bindir, libdir, etc.)\n  as well as configuration options to enable/disable certain features.\n\n- **Integrity of package and binaries on the system:** Since a package is being\n  installed (instead of binaries from a local build replacing existing binaries\n  owned by specific packages), the RPM database will show that everything looks\n  correct. In particular, you can use the `rpm -V` command to verify that the\n  files owned by your package have not been replaced or tampered with, which\n  will work correctly since the RPMs installed have the correct checksums of the\n  binaries built from the development tree.\n\n- **Properly handling configuration files:** Configuration files will be handled\n  in the same way as RPM upgrades from the distro, with `.rpmnew` and `.rpmsave`\n  files, rather than blindingly replacing them with defaults from the\n  development tree, which could easily happen if installing directly from the\n  tree to the system root filesystem.\n\n- **Easy to track currently running version:** By looking at the package name,\n  you can quickly see which branch was checked out when these binaries were\n  built, and using the information from `git describe` also present in the\n  \"Release:\" field, it is possible to check out the exact commit that was used\n  for this particular build.\n\n- **Ability to rollback and to switch builds:** Rolling back is easy using a\n  command such as `dnf downgrade` to go back to the packages from the distro. It\n  is also possible to keep multiple development builds and switch between them,\n  by simply using `rpm -U --oldpackage` to install a previous build, with no\n  need to check out a different branch on the source tree and rebuild those\n  binaries, or to keep multiple git worktrees around.\n\n- **Less interference from the normal distro package upgrades**: If you're\n  installing binaries over an existing package, if an upgrade for that package\n  becomes available and the machine has automatic updates configured, it will\n  most likely clobber the local binaries while installing that upgrade. By\n  having the development binaries installed through an RPM with a version string\n  that is most likely to be much larger than the one from the distro, it's\n  unlikely that newer distro packages will replace the development ones, thus\n  preventing them from being inadvertently replaced back with the release\n  version of the package while you were meaning to test the new version.\n\n- **Ability to install development binaries on other machines:** This is often\n  useful in machines that do not have a development environment present (so\n  wouldn't be able to run `make install` or `ninja install`, etc.) By building\n  packages from the development sources, it's easy to ship the packages to those\n  machines and simply install them using `rpm` or `dnf`, the tools that will be\n  already present there.\n\n## Advantages of git-rpmbuild over building a full RPM\n\nThere are other similar approaches that involve creating RPM packages from\ndevelopment trees (such as\n[`packit`](https://github.com/packit-service/packit)), but those typically\ninvolve packing the sources into an archive, building an SRPM and rebuilding\nthat from scratch every time.\n\nThis can be pretty time consuming, even when using caching for the compilation\nsteps (`ccache`). That makes these methods great for scheduled builds (nightly,\nweekly) and for background batch methods (integration testing, etc.) But they're\nnot great for development, when you're trying to build repeatedly and shaving\ntime off your commit/build/deploy/test cycle can improve your productivity\nsignificantly.\n\nTo illustrate the difference in both methods, see the videos below. To build\nsystemd RPMs from the SRPM package takes over 5 minutes on a fairly capable\nlaptop:\n\n[![asciicast](https://asciinema.org/a/268330.svg)](https://asciinema.org/a/268330)\n\nUsing a tool that would build a full-blown SRPM would take even longer, since\nthe `git archive` step must also be performed to generate an SRPM from the\nworktree.\n\nOn the other hand, to build those RPMs from a local development tree using\n`git rpmbuild` takes under 1 minute, since the build is incremental:\n\n[![asciicast](https://asciinema.org/a/268520.svg)](https://asciinema.org/a/268520)\n\nNote that it only takes 45 seconds, yet there is time to run all the tests and\nsave all the RPM packages on disk. Bringing 5 minutes down to 1 minute make\nquite a difference when you're actively developing and need a quick turnaround!\n\n## How does it work\n\nIt works by leveraging two arguments of `rpmbuild`:\n\n- `--build-in-place`: Build from locally checked out sources. Sets `_builddir`\n  to point to the current working directory.\n\n- `--noprep`: Skip the `%prep` step altogether. This means not only the source\n  tarball is not unpacked, but any patches from the RPM specfile will not be\n  applied.\n\nTogether, these result in a local build being performed and the normal build\ntools ensure an incremental build will be used, since the RPM build tree is now\nthe same as our development build tree.\n\n## Installing git-rpmbuild\n\nPre-requisite for the code is having Python 3.7 installed and having a working\n`rpmbuild` in the system, that's about it.\n\nTo work from git, simply clone the repository and make sure the `git-rpmbuild`\nscript is on the `$PATH`, either by adding the git worktree to `$PATH` or by\ncreating a symlink or copy of that script somewhere that's already in your\n`$PATH` (such as `~/.local/bin`, assuming you've added it.)\n\nI also maintain a COPR for git-rpmbuild for Fedora 30+ at:\nhttps://copr.fedorainfracloud.org/coprs/filbranden/git-rpmbuild/\n\nIn order to use it, simply enable it with:\n\n```\n$ sudo dnf copr enable filbranden/git-rpmbuild\n```\n\nAnd install the package using:\n\n```\n$ sudo dnf install git-rpmbuild\n```\n\n## Limitations\n\nThere are, of course, limitations to this approach.\n\nOnly packages which perform limited actions in the `%prep` step will work with\nthis approach. Typically that means only unpacking the source and applying\npatches for backports that are already present upstream. Since the whole `%prep`\nstep is skipped, the development tree must be similar enough to what the\nspecfile's `%build` and `%install` otherwise expect.\n\n(Here's [an\nexample](https://src.fedoraproject.org/rpms/systemd/c/05bb389ca4f3e17966d240bd0ae879f3f8c443fb?branch=master)\nof moving a step from `%prep` to `%install` in the specfile to solve one such\nproblem.)\n\nThis will also only work for packages that exist in Fedora, since that's where\nthe specfiles come from.\n\nIt also expects that the development worktree is close enough to what the latest\nspecfile is building, so that the instructions will still be applicable.\nSometimes if either development tree or specfile are having heavy changes, it's\nnot that easy to keep them both working in sync. Examples are files that are\nshipped and not declared under `%files`, or build instructions that have changed\nsince the build system has been tweaked or reconfigured.\n\nWe also need the RPM build not to mess with the source tree (otherwise those\nchanges will mess up our development environment.) One example of problematic\npackage here is selinux-policy, which builds from the same tree 3 times (for\neach type of policy, such as \"targeted\" and \"strict\") while replacing a handful\nof files before each build. That will surely break `git-rpmbuild`.\n\n`git-rpmbuild` also makes some assumptions about tags in the development git\nrepository, since it uses them to populate the \"Version:\" and \"Release:\" fields\nof the built RPMs. For now, it expects tags to match a version number, possibly\nincluding a simple \"v\" prefix to that number.\n\nThese packages are known to work with `git-rpmbuild`:\n\n- `systemd`\n- `numactl`\n- `oomd`\n- `meson`\n\nCurrently not working:\n\n- `rpm`: Tags in the development git repository are in the format\n  `rpm-${version}`, which currently wants to use `rpm` as a \"Version:\".\n  Additionally, as of `rpm-4.15.0-alpha-69-g858d6babd`, there's a build breakage\n  in `rpmmodule.c` about `variable 'moduledef' has initializer but incomplete\n  type` which needs some investigation.\n\n- `vim`: For some reason I get `error: Bad source:\n  ~/.local/share/git-rpmbuild/fedora-src/vim/vim-8.1-2019.tar.bz2:\n  No such file or directory`. It's expected that this file doesn't exist, but\n  it's unexpected that this would break the build, since with `--noprep` no one\n  should be trying to use it... I might need a version of RPM with more\n  debugging available to dig into this one, but see above about that 😆.\n  One more quirk of Vim is that the tags include patch number (such as\n  v8.1.2026), but the Vim specfile would prefer to use simply 8.1 as the version\n  and move 2026 to the \"Release:\" field only.\n\n- `asciinema`: Fails with `Installed (but unpackaged) file(s) found` for a\n  handful of Markdown files. Possibly easy to address in the specfile.\n\n## Related Projects, Future Ideas, etc.\n\nOne related project is [`packit`](https://github.com/packit-service/packit), in\nfact I started to look into whether I could include a feature such as this one\ninto `packit` itself rather than having a separate tool, but without much\nsuccess.\n\nI would like to see a similar approach for Debian-based systems, since often I\nwould like to test my systems on Ubuntu or Debian and being able to use a\nsimilar approach would be very nice. (See above for advantages.)\n\nObviously, having more packages working on `git-rpmbuild` is a big priority, so\nfeel free to report success/failure if you use it in any of your packages. PRs\naddressing issues that fix build of packages you care about are also very\nwelcome!\n\nI would like to use epochs to make versions of `git-rpmbuild` RPMs even newer\nthan distro packages, but there are some tricky cases when specfiles build\nmultiple packages and the packages depend on each other and they specify the\ndependency with an exact version match that doesn't include any epoch...\n(Parsing and generating specfiles is pretty hacky!)\n\nMore flexibility in handling the \"Release:\" tag would be nice.\n\nPer-package overrides, perhaps with a dotfile at the top of the git tree, or\nperhaps a local ConfigParser file somewhere in the user's home directory, would\nbe good if packages have special requirements that need to be configured for\nthose packages only.\n\nRight now there are no command-line arguments, but it would be nice to add\noptions to enable or disable certain features. Examples are generation of\ndebuginfo and debugsource packages (currently always disabled), or whether to\nrun the package tests during the RPM build step (currently always enabled.)\nProject name detection currently depends on the directory name, having a\ncommand-line argument/flag or per-project config file in the git tree to\noverride would also be a good idea.\n\nWhile the primary purpose of this package is to build RPMs in place from a\ndevelopment worktree, being able to generate a SRPM as well would be nice, as\nthat could be then used to feed a COPR repository and to automate nightly and\nweekly builds for projects.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilbranden%2Fgit-rpmbuild","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffilbranden%2Fgit-rpmbuild","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilbranden%2Fgit-rpmbuild/lists"}