Reputation: 91891
Imagine I'm working on an exploratory branch on a git repo and it only has one commit. I decide that my work is not needed any time soon, and I don't want to create a branch/tag. In fact, I'd like to throw away the changes, but just in case I ever need them again, I'd like to save a patch.
For purposes of this post, imagine I only have one change that I want to archive:
* 040cc7c (HEAD, ExperimentalBranch) This is where the experiment is
* a29ceb7 (master) This is the main branch
...
My proposed archive solution is as follows:
040cc7c
.ExperimentalBranch
from the repo.So far everything seems great, until years later when I might want to restore the patch. It will likely reference files/lines that are incompatible and not be able to be applied. To solve this, I could check out the patch's parent SHA and apply it there.
Therefore my proposed unarchive solution is as follows:
a29ceb7
.The only problem is that when I create the patch, I see that it contains SHA 040cc7c
, but does not mention a29ceb7
anywhere. It could be very hard for me to figure out the parent of 040cc7c
years after I created the patch. Furthermore, because I deleted the branch years earlier, I wouldn't expect there to be a git command that could help me discover the parent.
When creating a patch, is there a way to ensure that its parent SHA is included in the file as well?
My current workaround is to rename the patch to include the parent's SHA, but this can be easy to forget, and is more manual.
Upvotes: 2
Views: 160
Reputation: 4866
I wouldn't really recommend this as an archival strategy, but here's a way of creating an archive repo that stores a particular commit, without storing all of the other commits it is based on.
Create a minimal clone containing the base of the patch:
git clone --bare --depth 2 --filter=tree:0 -b patch-branch <url of repo with patch> archive-repo
This clone is both shallow (-depth
) and partial (—filter
). Disclaimer: I'm not sure whether these options are intended to be used together. The depth of the clone should be one more than the number of patch commits (we want the clone to include the patch commits and the base of the patches).
This has to be done with a real remote protocol, not a file:
URL or local path. And the remote needs to support filtering.
Render the patch commit to populate the partial clone with the trees and blobs referenced by the patch:
cd archive-repo
git show patch-branch > /dev/null
If you have multiple commits on the patch branch, repeat this for each of them.
(Optional) Pack the archive repository with git repack -ad
.
Store the archive repo as a tarball or however you prefer.
To restore, combine the archive repo with a repository containing the base of the patch. In my experiment, fetching or cloning from the archive as a local repo triggered population of additional objects into the partial clone. It probably wouldn’t with a git build that included commit 7b70e9ef. Pushing from the archive to a different repo seems to work.
Upvotes: 0
Reputation: 4732
I would suggest not to delete the branch, but if you really want to store the patch somewhere else, you may do
git format-patch --base HEAD^ HEAD^
so that the parent (base) is written in the patch
example:
$ git format-patch --base HEAD^ HEAD^
0001-test.patch
$ cat 0001-test.patch
From 057ff8fa3ba485abeb69156e9717570ad483d52c Mon Sep 17 00:00:00 2001
From: Dispeakable me <[email protected]>
Date: Sat, 27 Mar 2021 09:47:23 +0100
Subject: [PATCH] test
---
test.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/test.cpp b/test.cpp
index 6f4ed1e..1ef4295 100644
--- a/test.cpp
+++ b/test.cpp
@@ -1,4 +1,5 @@
+
#include <list>
class Semaphore {
base-commit: b50a780230e2f3f2be8bf6ad3797de272cafba5c
--
2.26.3
and you can check the parent sha1:
$ git cat-file -p HEAD
tree 5c03e768250fe7fe94d8ba0454feae422abd6aac
parent b50a780230e2f3f2be8bf6ad3797de272cafba5c
author Dispeakable me <[email protected]> 1616834843 +0100
committer Dispeakable me <[email protected]> 1616834843 +0100
test
Upvotes: 2