Fossil SCM
Another attempt at addressing forum critiques about the gitusers doc's Case Study 1. Also had to update the example date we're searching for again, so I addeed a paragraph explaining why the example might break again.
Commit
278a2b7453a759b8036104ea48e3446265ee2f6ce13ade553a442ede7c2643d1
Parent
18fc69710671d9f…
1 file changed
+29
-22
+29
-22
| --- www/gitusers.md | ||
| +++ www/gitusers.md | ||
| @@ -784,11 +784,11 @@ | ||
| 784 | 784 | My search engine’s first result for “git checkout by date” gives [a |
| 785 | 785 | highly-upvoted accepted answer on Stack Overflow][gcod]. It gives two |
| 786 | 786 | alternative commands, the first of which is based on Git’s [`rev-parse` |
| 787 | 787 | feature][grp]: |
| 788 | 788 | |
| 789 | - git checkout master@{2020-03-12} | |
| 789 | + git checkout master@{2020-03-17} | |
| 790 | 790 | |
| 791 | 791 | It’s a bit cryptic, but that’s not its major flaw: it only works if the |
| 792 | 792 | target commit is in Git’s [reflog], which Git [automatically |
| 793 | 793 | prunes][gle] to 90 days of history, by default. Worse, the command won’t |
| 794 | 794 | fail outright if the reflog can’t resolve the given date, it will |
| @@ -802,11 +802,11 @@ | ||
| 802 | 802 | from a purgeable and possibly-stale local cache. |
| 803 | 803 | |
| 804 | 804 | That same Stack Overflow answer therefore goes on to recommend an |
| 805 | 805 | entirely different command: |
| 806 | 806 | |
| 807 | - git checkout $(git rev-list -n 1 --first-parent --before="2020-03-12" master) | |
| 807 | + git checkout $(git rev-list -n 1 --first-parent --before="2020-03-17" master) | |
| 808 | 808 | |
| 809 | 809 | We believe you get such answers to Git help requests in part |
| 810 | 810 | because of its lack of an always-up-to-date [index into its log](#log) and in |
| 811 | 811 | part because of its “small tools loosely joined” design philosophy. This |
| 812 | 812 | sort of command is therefore composed piece by piece: |
| @@ -819,35 +819,36 @@ | ||
| 819 | 819 | user. |
| 820 | 820 | |
| 821 | 821 | “Oh, I know, I’ll search the rev-list, which outputs commit IDs by |
| 822 | 822 | parsing the log backwards from `HEAD`! Easy!” |
| 823 | 823 | |
| 824 | - git rev-list --before=2020-03-12 | |
| 824 | + git rev-list --before=2020-03-17 | |
| 825 | 825 | |
| 826 | 826 | “Blast! Forgot the commit ID!” |
| 827 | 827 | |
| 828 | - git rev-list --before=2020-03-12 master | |
| 828 | + git rev-list --before=2020-03-17 master | |
| 829 | 829 | |
| 830 | 830 | “Double blast! It just spammed my terminal with revision IDs! I need to |
| 831 | 831 | limit it to the single closest match: |
| 832 | 832 | |
| 833 | - git rev-list -n 1 --before=2020-03-12 master | |
| 833 | + git rev-list -n 1 --before=2020-03-17 master | |
| 834 | 834 | |
| 835 | 835 | “Okay, it gives me a single revision ID now, but is it what I’m after? |
| 836 | 836 | Let’s take a look…” |
| 837 | 837 | |
| 838 | - git show $(git rev-list -n 1 --before=2020-03-12 master) | |
| 838 | + git show $(git rev-list -n 1 --before=2020-03-17 master) | |
| 839 | 839 | |
| 840 | 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:” | |
| 841 | +Off to search the web… Okay, it says I need to give either the | |
| 842 | +`--first-parent` or `--no-merges` flag to show only regular commits, | |
| 843 | +not merge-commits. Let’s try the first one:” | |
| 843 | 844 | |
| 844 | - git show $(git rev-list -n 1 --no-merges --before=2020-03-12 master) | |
| 845 | + git show $(git rev-list -n 1 --first-parent --before=2020-03-17 master) | |
| 845 | 846 | |
| 846 | 847 | “Better. Let’s check it out:” |
| 847 | 848 | |
| 848 | - git checkout $(git rev-list -n 1 --no-merges --before=2020-03-12 master) | |
| 849 | + git checkout $(git rev-list -n 1 --first-parent --before=2020-03-17 master) | |
| 849 | 850 | |
| 850 | 851 | “Success, I guess?” |
| 851 | 852 | |
| 852 | 853 | <center>◆ ◆ ◆</center> |
| 853 | 854 | |
| @@ -863,35 +864,41 @@ | ||
| 863 | 864 | All of the command examples above were done on [Git’s own |
| 864 | 865 | repository][gitgh]. Your results with the first command — the one based |
| 865 | 866 | on [Git’s `rev-parse` feature][grp] — will vary depending on the state |
| 866 | 867 | of your local reflog. |
| 867 | 868 | |
| 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. | |
| 869 | +The date we’re using is simply our attempt to produce an example that | |
| 870 | +always points at the same merge commit. As I write this, it’s pointing | |
| 871 | +at [this one][gmc], but this is my third attempt: prior examples | |
| 872 | +(2020-04-12 and 2020-03-12) broke for no obvious reason, suggesting that | |
| 873 | +a given date in the above command isn’t always guaranteed to give the | |
| 874 | +same commit. These example dates are far enough back in history that I | |
| 875 | +doubt this is due to history rewriting. My pet hypothesis is that Git | |
| 876 | +isn’t always traversing the log strictly in date order, and the order of | |
| 877 | +entries in the log can shift about from one clone to the next, so the | |
| 878 | +commit “before” a given date might differ from one to the next. If | |
| 879 | +that’s true, then even the second command isn’t wholly reliable. | |
| 876 | 880 | |
| 877 | 881 | You may be asking with an exasperated huff, “What is your *point*, man?” |
| 878 | 882 | The point is that the equivalent in Fossil is simply: |
| 879 | 883 | |
| 880 | - fossil up 2020-03-12 | |
| 884 | + fossil up 2020-03-17 | |
| 881 | 885 | |
| 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. | |
| 886 | +…which will *always* give the commit closest to the 17th of March, 2020, | |
| 887 | +no matter whether you do it on a fresh clone or a stale one because of | |
| 888 | +Fossil’s autosync feature. Because this uses a SQLite indexed | |
| 889 | +“`ORDER BY`” query, the answer won’t shift about from one clone to the | |
| 890 | +next. | |
| 885 | 891 | |
| 886 | 892 | In Git terms, Fossil’s “reflog” is always complete and up-to-date. |
| 887 | 893 | |
| 888 | 894 | [gbash]: https://appuals.com/what-is-git-bash/ |
| 889 | 895 | [gcod]: https://stackoverflow.com/a/6990682/142454 |
| 890 | 896 | [gdh]: https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit/ |
| 891 | 897 | [gitgh]: https://github.com/git/git/ |
| 892 | 898 | [gle]: https://git-scm.com/docs/git-reflog#_options_for_expire |
| 899 | +[gmc]: https://github.com/git/git/commit/67b0a24910fbb23c8f5e7a2c61c339818bc68296 | |
| 893 | 900 | [grp]: https://git-scm.com/docs/git-rev-parse |
| 894 | 901 | [reflog]: https://git-scm.com/docs/git-reflog |
| 895 | 902 | |
| 896 | 903 | ---- |
| 897 | 904 | |
| 898 | 905 |
| --- www/gitusers.md | |
| +++ www/gitusers.md | |
| @@ -784,11 +784,11 @@ | |
| 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 |
| @@ -802,11 +802,11 @@ | |
| 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: |
| @@ -819,35 +819,36 @@ | |
| 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 | |
| @@ -863,35 +864,41 @@ | |
| 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 |
| --- www/gitusers.md | |
| +++ www/gitusers.md | |
| @@ -784,11 +784,11 @@ | |
| 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-17} |
| 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 |
| @@ -802,11 +802,11 @@ | |
| 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-17" 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: |
| @@ -819,35 +819,36 @@ | |
| 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-17 |
| 825 | |
| 826 | “Blast! Forgot the commit ID!” |
| 827 | |
| 828 | git rev-list --before=2020-03-17 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-17 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-17 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 either the |
| 842 | `--first-parent` or `--no-merges` flag to show only regular commits, |
| 843 | not merge-commits. Let’s try the first one:” |
| 844 | |
| 845 | git show $(git rev-list -n 1 --first-parent --before=2020-03-17 master) |
| 846 | |
| 847 | “Better. Let’s check it out:” |
| 848 | |
| 849 | git checkout $(git rev-list -n 1 --first-parent --before=2020-03-17 master) |
| 850 | |
| 851 | “Success, I guess?” |
| 852 | |
| 853 | <center>◆ ◆ ◆</center> |
| 854 | |
| @@ -863,35 +864,41 @@ | |
| 864 | All of the command examples above were done on [Git’s own |
| 865 | repository][gitgh]. Your results with the first command — the one based |
| 866 | on [Git’s `rev-parse` feature][grp] — will vary depending on the state |
| 867 | of your local reflog. |
| 868 | |
| 869 | The date we’re using is simply our attempt to produce an example that |
| 870 | always points at the same merge commit. As I write this, it’s pointing |
| 871 | at [this one][gmc], but this is my third attempt: prior examples |
| 872 | (2020-04-12 and 2020-03-12) broke for no obvious reason, suggesting that |
| 873 | a given date in the above command isn’t always guaranteed to give the |
| 874 | same commit. These example dates are far enough back in history that I |
| 875 | doubt this is due to history rewriting. My pet hypothesis is that Git |
| 876 | isn’t always traversing the log strictly in date order, and the order of |
| 877 | entries in the log can shift about from one clone to the next, so the |
| 878 | commit “before” a given date might differ from one to the next. If |
| 879 | that’s true, then even the second command isn’t wholly reliable. |
| 880 | |
| 881 | You may be asking with an exasperated huff, “What is your *point*, man?” |
| 882 | The point is that the equivalent in Fossil is simply: |
| 883 | |
| 884 | fossil up 2020-03-17 |
| 885 | |
| 886 | …which will *always* give the commit closest to the 17th of March, 2020, |
| 887 | no matter whether you do it on a fresh clone or a stale one because of |
| 888 | Fossil’s autosync feature. Because this uses a SQLite indexed |
| 889 | “`ORDER BY`” query, the answer won’t shift about from one clone to the |
| 890 | next. |
| 891 | |
| 892 | In Git terms, Fossil’s “reflog” is always complete and up-to-date. |
| 893 | |
| 894 | [gbash]: https://appuals.com/what-is-git-bash/ |
| 895 | [gcod]: https://stackoverflow.com/a/6990682/142454 |
| 896 | [gdh]: https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit/ |
| 897 | [gitgh]: https://github.com/git/git/ |
| 898 | [gle]: https://git-scm.com/docs/git-reflog#_options_for_expire |
| 899 | [gmc]: https://github.com/git/git/commit/67b0a24910fbb23c8f5e7a2c61c339818bc68296 |
| 900 | [grp]: https://git-scm.com/docs/git-rev-parse |
| 901 | [reflog]: https://git-scm.com/docs/git-reflog |
| 902 | |
| 903 | ---- |
| 904 | |
| 905 |