lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Retrieve file from git as of a particular date


From: Vadim Zeitlin
Subject: Re: [lmi] Retrieve file from git as of a particular date
Date: Sat, 15 Jun 2019 16:21:25 +0200

On Fri, 14 Jun 2019 15:24:23 +0000 Greg Chicares <address@hidden> wrote:

GC> Often we make a set of local changes, then move them aside (e.g., into
GC> a different subdirectory), and then undertake a different task in a
GC> clean checkout. The motivation might be to modify output in some way
GC> that can't go into production until it's been formally accepted by
GC> others. We may have quite a few pending changesets, and acceptances
GC> are asynchronous. The problem is that these changesets conflict with
GC> each other and with normal evolution in HEAD, so when one is eventually
GC> accepted, it can be hard to see what the intended change was.

 I'd like to start by replying to the last paragraph of your email:

GC> Or we could use 'git stash', which I have found to be useful for
GC> short-lived changes--but after several months the changes tend to
GC> go stale and can't be popped cleanly; besides, the contents are
GC> hard to view, and liable to be lost due to a fumbled command, so
GC> that's not a good solution for changes that may be put aside for
GC> months. We could also use git branches, but that alternative is
GC> very much like using a distinct "pending" directory--it's just a
GC> matter of storing changes in the OS filesystem or git's own--so I
GC> don't see any great advantage there. The essential problem is that
GC> merges are difficult, and really must be done manually.

 The advantage of using either "git stash" or separate branches is that
Git machinery can be used for merging later. Of course, if there are any
conflicts, i.e. if exactly the same line of code has been changed in both
the stashed change/commit on another branch and in master, merging will
still resolve in a conflict that will need to be manually resolved but this
is basically unavoidable. OTOH if the merge can be done automatically, it
will be done by Git, which is a big advantage compared to merging the files
manually. And you can also use the usual Git commands (show, diff etc) for
examining the changes if you don't remember what exactly was changed
several months later.

 To summarize, I think you already know the best answer to your question:
just create branches for your changes. Stashing them would work too, but I
agree that branches are better for periods of many months, especially if
you use some consistent naming convention for them, e.g. "pending/foo", so
that you can easily find them in git-branch output later.

GC> When we later want to commit the changes in, say,
GC>   /opt/lmi/pending/foo.cpp  dated 2019-03-21
GC> it's handy to retrieve 'foo.cpp' as it stood on the date it was moved
GC> to a "pending" directory--so that we can see what the intended changes
GC> were, and figure out how to apply them to current HEAD.

 This is something that would be immediately visible if you committed the
change to pending/foo branch as you could simply do

        git show pending/foo foo.cpp

to view the changes in the given file (of course, foo.cpp could be omitted
if it was the only file changed by this commit).

GC> How, then, can we retrieve a file as of a given date?
[... snip attempts using the wrong date format ...]
GC> Apparently git accepts "YYYY-MM-DD" but misinterprets "YYYYMMDD".

 Yes, exactly. I've been burnt by this a few times as well, so I can
sympathize -- but not do much else, i.e. I can't suggest anything else than
just having to remember that Git needs the dashes here.

GC> Retrying a simpler command from above:
GC> 
GC> # as above, without hyphens--no good
GC>   git show HEAD@{20181014}:antediluvian_stubs.cpp  
GC>   fatal: Log for 'HEAD' only has 973 entries.
GC> # Does that syntax mean the 20,181,014th preceding commit?

 Yes again, see gitrevisions(7).

GC> # with hyphens--seems to work, but see next example
GC>   git show HEAD@{2018-10-14}:antediluvian_stubs.cpp
GC> 
GC> # move date back a decade--no good (because of "reflog"?)
GC>   git show HEAD@{2008-10-14}:antediluvian_stubs.cpp 
GC>   warning: Log for 'HEAD' only goes back to Thu, 11 Oct 2018 23:33:18 +0000.

 Yes, Git reglogs default to only 90 days by default (this can be changed
via gc.reflogExpire setting).

GC> The rev-list method does however let me go back a decade:
GC>   git show `git rev-list -1 --before=2008-10-14 
master`:antediluvian_stubs.cpp
GC> That works, so it's the best solution I've found.

 I'm afraid I can't propose anything better. git-show doesn't take
git-rev-list options, so you can't use --before with it directly, while
git-log does accept this option, but can only show you the diff, not the
entire file. So, as far as the answer to the question in the subject of
this email goes, this is the answer and the only improvement I can suggest
is creating a Git alias for it if you plan on using this command often
enough. However I still think that you don't need an answer to this
question at all because you should never need to do it in the first place.

GC> There are other ways we could approach the motivating problem.
GC> For example, when moving a file aside, we might also store:
GC>   - the contemporary unmodified original
GC>   - a patch embodying the change
GC> yet that makes extra work that would often turn out to be unneeded.

 This would just duplicate even more things that Git does automatically for
you and I see absolutely no reason to do it. Just create a branch which can
be used as a symbolic bookmark for your change and it will solve all of the
problems mentioned in this email, while providing other advantages, such as
the possibility of backing up your changes by just pushing your branches to
Savannah or rebasing them (which can be simpler than merging for some kinds
of changes) later.

 There is, of course, no such thing as a bad question, but I'd say that
there is such thing as a batter question and in this case asking "How can I
put aside my changes before integrating them into master" would definitely
be a better one. And the answer to it is pretty unequivocal: commit these
changes to a branch, that will be merged (or cherry-picked if you prefer)
later.

 Regards,
VZ

Attachment: pgprDKb2Oki3s.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]