summaryrefslogtreecommitdiff
path: root/src/content/tils/2020/08/14/browse-git.adoc
blob: 3d7660eb050d1aa2ebb15406934fa2dd325cbf18 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
= Browse a git repository at a specific commit
:categories: git

I commonly use tools like `git log` together with `git show` when inspecting
past changes in a repository:

[source,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:

[source,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.  This is what `man git` says about it:

[source,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/`:

[source,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:

[source,shell]
----
git --work-tree=<dir> checkout <my-commit> -- .
----

There's an extra `-- .` at the end, which initially looks like we're sending
Morse signals to git, but we're actually saying to `git-checkout` which sub
directory of `<my-commit>` we want to look at.  Which means we can do something
like:

[source,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.

== References

:so-link: https://stackoverflow.com/a/16493707

. {so-link}[GIT: Checkout to a specific folder] (StackOverflow)