Masklinn
Masklinn

Reputation: 42197

Does git support applying patches (`.patch` files) to tree-ish?

I've got a server serving git repositories, bare, they can be pulled from and pushed to as normal.

For convenience, I'd like to support sending patches via a side channel and having those patches get applied to relevant branches by the server.

However as far as I can tell neither git am nor git apply support working with bare repositories, applying patches to tree-ish objects.

Obviously it's always possible to create a worktree or clone-with-working copy and apply patches to that, but that's a lot of FS churn, so I wanted to know if there's a way to do that built-in, without having to parse and apply patches "by hand" to individual blobs.

Upvotes: 0

Views: 98

Answers (1)

jthill
jthill

Reputation: 60235

Obviously it's always possible to create a worktree or clone-with-working copy and apply patches to that, but that's a lot of FS churn

Git has always been able to do minimum-checkout merge/apply, you never needed to do a full checkout for this.

If you're on a server in a bare clone and want to update HEAD,

$ git clone -ns . `mktemp -d`; cd $_
$ git read-tree HEAD
$ git apply -3 <the.patch

and apply will get only what it needs. You can then git commit-tree the tree git write-tree makes and push the resulting commit back to exactly where you want.

I did this with a Git patch I got off the mailing list, "[PATCH 1/6] refs: properly apply exclude patterns to namespaced refs", it took basically nothing. There's some extra shenanigans here to apply on a commit that hasn't yet been patched, you'll see:

[jthill@denisov jthill]$ cd git
/home/jthill/src/git
[jthill@denisov git]$ git pull
[…]
[jthill@denisov git]$ git tag fixit $(git log -1 --pretty=%H --grep 'properly apply exclude' --all)^
[jthill@denisov git]$ git clone -nsb fixit . `mktemp -d`; cd $_
Cloning into '/tmp/jthill/tmp.FywiM3hlPc'...
done.
[jthill@denisov tmp.FywiM3hlPc]$ git read-tree HEAD
[jthill@denisov tmp.FywiM3hlPc]$ wl-paste|sed s,\\r$,,|git apply --cached -3
Applied patch to 'refs.c' cleanly.
Applied patch to 'refs.h' cleanly.
Applied patch to 't/t5509-fetch-push-namespaces.sh' cleanly.
[jthill@denisov tmp.FywiM3hlPc]$ git commit -m-
[detached HEAD 1a94891ac0] -
 3 files changed, 41 insertions(+), 4 deletions(-)
[jthill@denisov tmp.FywiM3hlPc]$ du -sh .git .
672K    .git
4.0K    .
[jthill@denisov tmp.FywiM3hlPc]$

Upvotes: 1

Related Questions