aboutsummaryrefslogtreecommitdiff
path: root/_tils
diff options
context:
space:
mode:
Diffstat (limited to '_tils')
-rw-r--r--_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md72
1 files changed, 72 insertions, 0 deletions
diff --git a/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md b/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md
new file mode 100644
index 0000000..ad7be6d
--- /dev/null
+++ b/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md
@@ -0,0 +1,72 @@
+---
+title: Browse a git repository at a specific commit
+date: 2020-08-13
+layout: til
+lang: en
+ref: browse-a-git-repository-at-a-specific-commit
+---
+
+I commonly use tools like `git log` together with `git show` when inspecting
+past changes in a repository:
+
+```shell
+git log
+# search for a the commit I'm looking for
+git show <my-commit>
+# see the diff for the commit
+```
+
+But I also wanted to not only be able to look at the diff of a specific commit,
+but to browse the whole repository at that specific commit.
+
+I used to accomplish it the "brute force" way: clone the whole repository in
+another folder and checkout the commit there:
+
+```shell
+git clone <original-repo> /tmp/tmp-repo-clone
+cd /tmp-repo-clone
+git checkout <my-commit>
+```
+
+But git itself allows we to specific the directory of the checkout by using the
+`--work-tree` global git flag[^src]. This is what `man git` says about it:
+
+```txt
+--work-tree=<path>
+ Set the path to the working tree. It can be an absolute path or a path relative to the current working
+ directory. This can also be controlled by setting the GIT_WORK_TREE environment variable and the
+ core.worktree configuration variable (see core.worktree in git-config(1) for a more detailed
+ discussion).
+```
+
+So it allows us to set the desired path of the working tree. So if we want to
+copy the contents of the current working tree into `copy/`:
+
+```shell
+mkdir copy
+git --work-tree=copy/ checkout .
+```
+
+After that `copy/` will contain a replica of the code in HEAD. But to checkout a
+specific, we need some extra parameters:
+
+```shell
+git --work-tree=<dir> checkout <my-commit> -- .
+```
+
+There's an extra `-- .` at the end, which initally looks like we're sending
+morse signals to git, but we're actually saying to `git-checkout` which subdir
+of `<my-commit>` we want to look at. Which means we can do something like:
+
+```shell
+git --work-tree=<dir> checkout <my-commit> -- src/
+```
+
+And with that `<dir>` will only contain what was inside `src/` at `<commit>`.
+
+After any of those checkouts, you have to `git reset .` to reset your current
+staging area back to what it was before the checkout.
+
+[^src]: I found out about this with [this StackOverflow answer][0].
+
+[0]: https://stackoverflow.com/questions/5283262/what-is-git-work-tree-why-have-i-never-needed-to-set-this-env-var-why-now