[darcs-users] How do I purge a binary from my repository?

Aaron Kaplan lists2546 at aaronkaplan.info
Sun Mar 22 16:05:39 UTC 2009

On Tue, 10 Feb 2009 20:01:49 +0000
Eric Kow <kowey at darcs.net> wrote:

> Hi Aaron,
> Is there any chance you would like to try your hand at helping Lyle out?
> It may be good research for whether we need a darcs transplant command
> or not.

Sorry, it took me a while to get around to writing up the results.  To
summarize, Lyle's question was the following:

> On Tue, Feb 10, 2009 at 11:25:14 -0800, Lyle Kopnicky wrote:
> > I had
> > accidentally overwritten my project's LICENSE.txt file with a binary
> > (apparently a distribution tarball). It was recorded as part of a patch
> > along with other useful changes. I was able to fix the file by recreating it
> > and recording the change. But now I have two giant patches in my repository:
> > one to add the binary (along with other changes) and another to remove it.
> > 
> > What's the safest and most straightforward way to purge these copies of the
> > binary from my history?

If the change he wanted to get rid of were in a patch by itself, all
he'd have to do would be obliterate that patch, but in this case the
unwanted change is in the same patch as some changes he wants to keep.
If he had caught the mistake soon after recording it, he could have
unrecorded the problematic patch and re-recorded just the desired part
of it, but in this case there are many subsequent patches that depend on
(the desired part of) the problematic patch.  Unrecording and
re-recording all of them would take a lot of manual effort.

In this kind of situation, one would like to be able to split the
problematic patch into two separate patches, one containing the
undesired part and the other containing the desired part, and then
obliterate the undesired part.  It would be nice to be able to replace
a patch with two patches that together have the same effect, without
changing the subsequent history.  (I believe this functionality would
be quite generally useful.  It often happens to me that some time after
committing a change, I realize that I should have broken it up
differently, e.g. because I want to pull just part of the change into
a different branch.  Currently the common wisdom is that you should
break your changes up in as fine-grained a way as possible, so that
you never find yourself in this kind of situation.  But it can be a lot
of work to do it this way, especially if you're careful about recording
explicit dependencies that darcs can't detect automatically.  It would
be nice to be able to record in big chunks initially, and be able to go
back and break them up later.)

In principle, I think the darcs 2 semantics do allow this kind of
operation.  In a temporary repo, pull all changes up to and including
the one you want to split.  Unrecord it, and rerecord the parts
separately. Now pull in the entire history, including the original
problematic patch. The newly recorded patches and the original
problematic patch make the same changes.  Under darcs 1 they would have
been considered to conflict, but under darcs 2 semantics they aren't;
instead, the subsequent patches that depend on those changes are
considered to depend on the presence of either the problematic patch or
the new ones. So now you can obliterate the problematic patch, leaving
the rest of the history intact.

Lyle and I tried applying this procedure in a couple of different ways,
and essentially it works, but the repository ends up in a state where
certain operations result in error messages.  In this case, the message
was "darcs: bug in get_extra commuting patches:". I previously reported
getting the error "patches to commute_to_end does not commutex (1) at
src/Darcs/Patch/Depends.hs:452" after a similar operation (see
http://bugs.darcs.net/issue1327 ).

Lyle did eventually manage to get his repository in the state he
wanted, but only by doing part of the work using unrecord and re-record.

Below I include the exact steps I took.  Lyle tells me the
version of the repo with the unwanted patch is no longer publicly
available, but maybe he'd give it to you if you ask. (I also have a
copy, which I'd share with his permission.)

Please CC me on replies.

darcs get http://patch-tag.com/publicrepos/vintage-basic

darcs get --to-patch=add-external-documentation vintage-basic temp

cd temp

darcs unrecord --all -p add-external-documentation

darcs revert --all LICENSE.txt

darcs record --all -m "add-external-documentation without the
unintended change to LICENSE.txt"

darcs pull --all

darcs obliterate -p add-external-documentation
(answer y t fix-broken-license-file, add-external-documentation; n to
everything else)

(darcs pull --dry-run gives:
darcs: bug in get_extra commuting patches:
First patch is:
Wed Feb 11 23:04:12 CET 2009  mi
  * add-external-documentation without the unintended change to
LICENSE.txt Second patch is:
Fri Jan  9 07:04:50 CET 2009  lyle at vintage-basic.net
  * ignore-carriage-return-preceding-a-newline

More information about the darcs-users mailing list