Fossil SCM

Flipped the examples in Case Study 1 in gitusers.md around so we approach the problem the same way the SO answer did. Also changed the target date, since on my local Git clone, the prior date is now giving me a non-merge commit for some reason. Rather than try to explain the discrepancy, I've just picked a different example.

wyoung 2020-11-04 15:45 trunk
Commit 8f96db71d3fec99914ff97cccfc585b932f01c9bd9a5743007ea744fffddc6de
1 file changed +50 -68
+50 -68
--- www/gitusers.md
+++ www/gitusers.md
@@ -773,30 +773,43 @@
773773
774774
## <a id="cvdate" name="cs1"></a> Case Study 1: Checking Out A Version By Date
775775
776776
Let’s get into something a bit more complicated: a case study showing
777777
how the concepts lined out above cause Fossil to materially differ in
778
-day-to-day operation from Git.
779
-
780
-You may need to check out
778
+day-to-day operation from Git. The goal: you need to check out
781779
a version of a project by date. Perhaps your customer gave you a
782780
vague bug report referencing only a date rather than a version, or perhaps you’re
783781
poking semi-randomly through history to find a “good” version to anchor
784782
the start point of a [`bisect`][bis] operation.
785783
786
-Because Git doesn’t maintain comprehensive lookup tables into its log —
787
-[as detailed above](#log) — you will find pages online recommending
788
-long, nested commands like this:
789
-
790
- git checkout $(git rev-list -n 1 --first-parent --before="2020-04-12" master)
791
-
792
-That’s [the top answer on Stack Overflow][gcod] for
793
-“git checkout by date” as surfaced by the web search engine I used,
794
-its first search result.
784
+My search engine’s first result for “git checkout by date” gives [a
785
+highly-upvoted accepted answer on Stack Overflow][gcod]. It gives two
786
+alternative commands, the first of which is based on Git’s [`rev-parse`
787
+feature][grp]:
788
+
789
+ git checkout master@{2020-03-12}
790
+
791
+It’s a bit cryptic, but that’s not its major flaw: it only works if the
792
+target commit is in Git’s [reflog], which Git [automatically
793
+prunes][gle] to 90 days of history, by default. Worse, the command won’t
794
+fail outright if the reflog can’t resolve the given date, it will
795
+instead give an *incorrect* result on `stdout`, being the closest it can
796
+come to your requested date, even if that’s months or years out from
797
+your target! I’ve even managed to get it to give an incorrect result
798
+without the warning by running it on stale Git clones.
799
+
800
+In other words, Git tries its best, and it may or may not warn if it
801
+fails, but it absolutely should never be trusted, because it’s working
802
+from a purgeable and possibly-stale local cache.
803
+
804
+That same Stack Overflow answer therefore goes on to recommend an
805
+entirely different command:
806
+
807
+ git checkout $(git rev-list -n 1 --first-parent --before="2020-03-12" master)
795808
796809
We believe you get such answers to Git help requests in part
797
-because of its lack of an always-up-to-date index into its log and in
810
+because of its lack of an always-up-to-date [index into its log](#log) and in
798811
part because of its “small tools loosely joined” design philosophy. This
799812
sort of command is therefore composed piece by piece:
800813
801814
<center>◆  ◆  ◆</center>
802815
@@ -806,37 +819,35 @@
806819
user.
807820
808821
“Oh, I know, I’ll search the rev-list, which outputs commit IDs by
809822
parsing the log backwards from `HEAD`! Easy!”
810823
811
- git rev-list --before=2020-04-12
824
+ git rev-list --before=2020-03-12
812825
813826
“Blast! Forgot the commit ID!”
814827
815
- git rev-list --before=2020-04-12 master
828
+ git rev-list --before=2020-03-12 master
816829
817830
“Double blast! It just spammed my terminal with revision IDs! I need to
818831
limit it to the single closest match:
819832
820
- git rev-list -n 1 --before=2020-04-12 master
833
+ git rev-list -n 1 --before=2020-03-12 master
821834
822835
“Okay, it gives me a single revision ID now, but is it what I’m after?
823836
Let’s take a look…”
824837
825
- git show $(git rev-list -n 1 --before=2020-04-12 master)
838
+ git show $(git rev-list -n 1 --before=2020-03-12 master)
826839
827
-“Um… Why does it give me a commit from 2019-12-15? Maybe that was when
828
-it was committed on another branch, and I’m seeing a merge-commit made
829
-months later? Off to search the web… Okay, it says I need to give the
840
+“Oops, that’s giving me a merge commit, not what I want.
841
+Off to search the web… Okay, it says I need to give the
830842
`--no-merges` flag to show only regular commits, not merge-commits:”
831843
832
- git show $(git rev-list -n 1 --no-merges --before=2020-04-12 master)
844
+ git show $(git rev-list -n 1 --no-merges --before=2020-03-12 master)
833845
834
-“Well poop: it shows the same commit! Eff it; let’s just try it and hope
835
-it’s close enough.”
846
+“Better. Let’s check it out:”
836847
837
- git checkout $(git rev-list -n 1 --no-merges --before=2020-04-12 master)
848
+ git checkout $(git rev-list -n 1 --no-merges --before=2020-03-12 master)
838849
839850
“Success, I guess?”
840851
841852
<center>◆  ◆  ◆</center>
842853
@@ -847,70 +858,41 @@
847858
848859
And too bad if you’re a Windows user who doesn’t want to use [Git
849860
Bash][gbash], since neither of the stock OS command shells have a
850861
command interpolation feature needed to run that horrid command.
851862
852
-If you think the bit about “a commit from 2019-12-15” in my
853
-little story above is made up, try `git rev-parse master@{2020-04-12}`
854
-on [Git’s own repository][gitgh]: it gives [this commit][grpgh]! Though
855
-GitHub shows the date we asked for, the `git show` command above gives
856
-the confusing result referenced in the story.
857
-This fixup within GitHub is success, of a sort, though it leaves us wondering why there’s a
858
-discrepancy.
863
+All of the command examples above were done on [Git’s own
864
+repository][gitgh]. Your results with the first command — the one based
865
+on [Git’s `rev-parse` feature][grp] — will vary depending on the state
866
+of your local reflog.
859867
860868
You may have noticed the difference between my story’s final command and
861869
the one given on Stack Overflow: `--first-parent` versus `--no-merges`.
862870
As far as I can tell, the SO answer is wrong, a conclusion I came to
863
-while writing this case study and finding that the command didn’t do what the SO answer claimed it did.
864
-None of the other answers on that page give the `--no-merges` option, either. This is
865
-one of the sneaky problems with complicated commands: people copy them
866
-around from place to place without trying to understand them first, so
867
-errors propagate.
868
-
869
-But hark! The same Stack Overflow answer gives a much simpler
870
-alternative based on Git’s [`rev-parse` feature][grp]:
871
-
872
- git checkout master@{2020-04-12}
873
-
874
-It’s a bit cryptic, but it’s much nicer than the prior command.
875
-
876
-Too bad it only works if the target commit is in Git’s [reflog], which
877
-Git [automatically prunes][gle] to 90 days of history from time to time. But
878
-the above command won’t fail outright if the reflog can’t resolve the
879
-given date, it will instead give an *incorrect* result on `stdout`,
880
-*possibly* accompanied by a warning on *stderr!* While I was writing
881
-this, it happily gave me a commit from 2019-07-19 until I nuked the
882
-repository and re-cloned, after which it at least warned me that the
883
-reflog didn’t go back that far… But it still gave me an answer: a wrong
884
-one!
885
-
886
-Why? Because Git lacks comprehensive up-to-date indices into its log,
887
-and my clone was stale, apparently last updated in July of 2019.
888
-When I nuked my stale clone and re-cloned, my
889
-command above started giving me today’s latest commit, that being as far
890
-back in history as it could dig. Who wants this behavior?
891
-
892
-Well, at least it works on Windows… That’s something!
893
-
894
-But woe betide you if you leave off the `master` bit. Or forget some bit
895
-of the cryptic punctuation.
871
+while writing this case study and finding that the command didn’t do
872
+what the SO answer claimed it did. None of the other answers on that
873
+page give the `--no-merges` option, either. This is one of the sneaky
874
+problems with complicated commands: people copy them around from place
875
+to place without trying to understand them first, so errors propagate.
896876
897877
You may be asking with an exasperated huff, “What is your *point*, man?”
898878
The point is that the equivalent in Fossil is simply:
899879
900
- fossil up 2020-04-12
880
+ fossil up 2020-03-12
881
+
882
+…and the commit will *always* be the one closest to the 12th of March, 2020, no matter
883
+whether it’s a fresh clone or a stale one because of Fossil’s autosync
884
+feature.
901885
902
-…and the commit will *always* be the one closest to the 12th of April, 2020, no matter
903
-whether it’s a fresh clone or a stale one.
886
+In Git terms, Fossil’s “reflog” is always complete and up-to-date.
904887
905888
[gbash]: https://appuals.com/what-is-git-bash/
906889
[gcod]: https://stackoverflow.com/a/6990682/142454
907890
[gdh]: https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit/
908891
[gitgh]: https://github.com/git/git/
909892
[gle]: https://git-scm.com/docs/git-reflog#_options_for_expire
910893
[grp]: https://git-scm.com/docs/git-rev-parse
911
-[grpgh]: https://github.com/git/git/commit/a99bc27aec74071aa1
912894
[reflog]: https://git-scm.com/docs/git-reflog
913895
914896
----
915897
916898
## <a id="morigin" name="cs2"></a> Case Study 2: Multiple "origin" Servers
917899
--- www/gitusers.md
+++ www/gitusers.md
@@ -773,30 +773,43 @@
773
774 ## <a id="cvdate" name="cs1"></a> Case Study 1: Checking Out A Version By Date
775
776 Let’s get into something a bit more complicated: a case study showing
777 how the concepts lined out above cause Fossil to materially differ in
778 day-to-day operation from Git.
779
780 You may need to check out
781 a version of a project by date. Perhaps your customer gave you a
782 vague bug report referencing only a date rather than a version, or perhaps you’re
783 poking semi-randomly through history to find a “good” version to anchor
784 the start point of a [`bisect`][bis] operation.
785
786 Because Git doesn’t maintain comprehensive lookup tables into its log —
787 [as detailed above](#log) — you will find pages online recommending
788 long, nested commands like this:
789
790 git checkout $(git rev-list -n 1 --first-parent --before="2020-04-12" master)
791
792 That’s [the top answer on Stack Overflow][gcod] for
793 “git checkout by date” as surfaced by the web search engine I used,
794 its first search result.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
795
796 We believe you get such answers to Git help requests in part
797 because of its lack of an always-up-to-date index into its log and in
798 part because of its “small tools loosely joined” design philosophy. This
799 sort of command is therefore composed piece by piece:
800
801 <center>◆  ◆  ◆</center>
802
@@ -806,37 +819,35 @@
806 user.
807
808 “Oh, I know, I’ll search the rev-list, which outputs commit IDs by
809 parsing the log backwards from `HEAD`! Easy!”
810
811 git rev-list --before=2020-04-12
812
813 “Blast! Forgot the commit ID!”
814
815 git rev-list --before=2020-04-12 master
816
817 “Double blast! It just spammed my terminal with revision IDs! I need to
818 limit it to the single closest match:
819
820 git rev-list -n 1 --before=2020-04-12 master
821
822 “Okay, it gives me a single revision ID now, but is it what I’m after?
823 Let’s take a look…”
824
825 git show $(git rev-list -n 1 --before=2020-04-12 master)
826
827 “Um… Why does it give me a commit from 2019-12-15? Maybe that was when
828 it was committed on another branch, and I’m seeing a merge-commit made
829 months later? Off to search the web… Okay, it says I need to give the
830 `--no-merges` flag to show only regular commits, not merge-commits:”
831
832 git show $(git rev-list -n 1 --no-merges --before=2020-04-12 master)
833
834 “Well poop: it shows the same commit! Eff it; let’s just try it and hope
835 it’s close enough.”
836
837 git checkout $(git rev-list -n 1 --no-merges --before=2020-04-12 master)
838
839 “Success, I guess?”
840
841 <center>◆  ◆  ◆</center>
842
@@ -847,70 +858,41 @@
847
848 And too bad if you’re a Windows user who doesn’t want to use [Git
849 Bash][gbash], since neither of the stock OS command shells have a
850 command interpolation feature needed to run that horrid command.
851
852 If you think the bit about “a commit from 2019-12-15” in my
853 little story above is made up, try `git rev-parse master@{2020-04-12}`
854 on [Git’s own repository][gitgh]: it gives [this commit][grpgh]! Though
855 GitHub shows the date we asked for, the `git show` command above gives
856 the confusing result referenced in the story.
857 This fixup within GitHub is success, of a sort, though it leaves us wondering why there’s a
858 discrepancy.
859
860 You may have noticed the difference between my story’s final command and
861 the one given on Stack Overflow: `--first-parent` versus `--no-merges`.
862 As far as I can tell, the SO answer is wrong, a conclusion I came to
863 while writing this case study and finding that the command didn’t do what the SO answer claimed it did.
864 None of the other answers on that page give the `--no-merges` option, either. This is
865 one of the sneaky problems with complicated commands: people copy them
866 around from place to place without trying to understand them first, so
867 errors propagate.
868
869 But hark! The same Stack Overflow answer gives a much simpler
870 alternative based on Git’s [`rev-parse` feature][grp]:
871
872 git checkout master@{2020-04-12}
873
874 It’s a bit cryptic, but it’s much nicer than the prior command.
875
876 Too bad it only works if the target commit is in Git’s [reflog], which
877 Git [automatically prunes][gle] to 90 days of history from time to time. But
878 the above command won’t fail outright if the reflog can’t resolve the
879 given date, it will instead give an *incorrect* result on `stdout`,
880 *possibly* accompanied by a warning on *stderr!* While I was writing
881 this, it happily gave me a commit from 2019-07-19 until I nuked the
882 repository and re-cloned, after which it at least warned me that the
883 reflog didn’t go back that far… But it still gave me an answer: a wrong
884 one!
885
886 Why? Because Git lacks comprehensive up-to-date indices into its log,
887 and my clone was stale, apparently last updated in July of 2019.
888 When I nuked my stale clone and re-cloned, my
889 command above started giving me today’s latest commit, that being as far
890 back in history as it could dig. Who wants this behavior?
891
892 Well, at least it works on Windows… That’s something!
893
894 But woe betide you if you leave off the `master` bit. Or forget some bit
895 of the cryptic punctuation.
896
897 You may be asking with an exasperated huff, “What is your *point*, man?”
898 The point is that the equivalent in Fossil is simply:
899
900 fossil up 2020-04-12
 
 
 
 
901
902 …and the commit will *always* be the one closest to the 12th of April, 2020, no matter
903 whether it’s a fresh clone or a stale one.
904
905 [gbash]: https://appuals.com/what-is-git-bash/
906 [gcod]: https://stackoverflow.com/a/6990682/142454
907 [gdh]: https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit/
908 [gitgh]: https://github.com/git/git/
909 [gle]: https://git-scm.com/docs/git-reflog#_options_for_expire
910 [grp]: https://git-scm.com/docs/git-rev-parse
911 [grpgh]: https://github.com/git/git/commit/a99bc27aec74071aa1
912 [reflog]: https://git-scm.com/docs/git-reflog
913
914 ----
915
916 ## <a id="morigin" name="cs2"></a> Case Study 2: Multiple "origin" Servers
917
--- www/gitusers.md
+++ www/gitusers.md
@@ -773,30 +773,43 @@
773
774 ## <a id="cvdate" name="cs1"></a> Case Study 1: Checking Out A Version By Date
775
776 Let’s get into something a bit more complicated: a case study showing
777 how the concepts lined out above cause Fossil to materially differ in
778 day-to-day operation from Git. The goal: you need to check out
 
 
779 a version of a project by date. Perhaps your customer gave you a
780 vague bug report referencing only a date rather than a version, or perhaps you’re
781 poking semi-randomly through history to find a “good” version to anchor
782 the start point of a [`bisect`][bis] operation.
783
784 My search engine’s first result for “git checkout by date” gives [a
785 highly-upvoted accepted answer on Stack Overflow][gcod]. It gives two
786 alternative commands, the first of which is based on Git’s [`rev-parse`
787 feature][grp]:
788
789 git checkout master@{2020-03-12}
790
791 It’s a bit cryptic, but that’s not its major flaw: it only works if the
792 target commit is in Git’s [reflog], which Git [automatically
793 prunes][gle] to 90 days of history, by default. Worse, the command won’t
794 fail outright if the reflog can’t resolve the given date, it will
795 instead give an *incorrect* result on `stdout`, being the closest it can
796 come to your requested date, even if that’s months or years out from
797 your target! I’ve even managed to get it to give an incorrect result
798 without the warning by running it on stale Git clones.
799
800 In other words, Git tries its best, and it may or may not warn if it
801 fails, but it absolutely should never be trusted, because it’s working
802 from a purgeable and possibly-stale local cache.
803
804 That same Stack Overflow answer therefore goes on to recommend an
805 entirely different command:
806
807 git checkout $(git rev-list -n 1 --first-parent --before="2020-03-12" master)
808
809 We believe you get such answers to Git help requests in part
810 because of its lack of an always-up-to-date [index into its log](#log) and in
811 part because of its “small tools loosely joined” design philosophy. This
812 sort of command is therefore composed piece by piece:
813
814 <center>◆  ◆  ◆</center>
815
@@ -806,37 +819,35 @@
819 user.
820
821 “Oh, I know, I’ll search the rev-list, which outputs commit IDs by
822 parsing the log backwards from `HEAD`! Easy!”
823
824 git rev-list --before=2020-03-12
825
826 “Blast! Forgot the commit ID!”
827
828 git rev-list --before=2020-03-12 master
829
830 “Double blast! It just spammed my terminal with revision IDs! I need to
831 limit it to the single closest match:
832
833 git rev-list -n 1 --before=2020-03-12 master
834
835 “Okay, it gives me a single revision ID now, but is it what I’m after?
836 Let’s take a look…”
837
838 git show $(git rev-list -n 1 --before=2020-03-12 master)
839
840 “Oops, that’s giving me a merge commit, not what I want.
841 Off to search the web… Okay, it says I need to give the
 
842 `--no-merges` flag to show only regular commits, not merge-commits:”
843
844 git show $(git rev-list -n 1 --no-merges --before=2020-03-12 master)
845
846 “Better. Let’s check it out:”
 
847
848 git checkout $(git rev-list -n 1 --no-merges --before=2020-03-12 master)
849
850 “Success, I guess?”
851
852 <center>◆  ◆  ◆</center>
853
@@ -847,70 +858,41 @@
858
859 And too bad if you’re a Windows user who doesn’t want to use [Git
860 Bash][gbash], since neither of the stock OS command shells have a
861 command interpolation feature needed to run that horrid command.
862
863 All of the command examples above were done on [Git’s own
864 repository][gitgh]. Your results with the first command — the one based
865 on [Git’s `rev-parse` feature][grp] — will vary depending on the state
866 of your local reflog.
 
 
 
867
868 You may have noticed the difference between my story’s final command and
869 the one given on Stack Overflow: `--first-parent` versus `--no-merges`.
870 As far as I can tell, the SO answer is wrong, a conclusion I came to
871 while writing this case study and finding that the command didn’t do
872 what the SO answer claimed it did. None of the other answers on that
873 page give the `--no-merges` option, either. This is one of the sneaky
874 problems with complicated commands: people copy them around from place
875 to place without trying to understand them first, so errors propagate.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
876
877 You may be asking with an exasperated huff, “What is your *point*, man?”
878 The point is that the equivalent in Fossil is simply:
879
880 fossil up 2020-03-12
881
882 …and the commit will *always* be the one closest to the 12th of March, 2020, no matter
883 whether it’s a fresh clone or a stale one because of Fossil’s autosync
884 feature.
885
886 In Git terms, Fossil’s “reflog” is always complete and up-to-date.
 
887
888 [gbash]: https://appuals.com/what-is-git-bash/
889 [gcod]: https://stackoverflow.com/a/6990682/142454
890 [gdh]: https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit/
891 [gitgh]: https://github.com/git/git/
892 [gle]: https://git-scm.com/docs/git-reflog#_options_for_expire
893 [grp]: https://git-scm.com/docs/git-rev-parse
 
894 [reflog]: https://git-scm.com/docs/git-reflog
895
896 ----
897
898 ## <a id="morigin" name="cs2"></a> Case Study 2: Multiple "origin" Servers
899

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button