1
- $ git init -q 1 > / dev/ null
1
+ $ git init -q 1 >/ dev/ null
2
2
3
3
Initial commit of main branch
4
4
$ echo contents1 > file1
5
5
$ git add .
6
- $ git commit -m " add file1" 1 > / dev/ null
6
+ $ git commit -m " add file1" 1 >/ dev/ null
7
7
8
8
Initial commit of subtree branch
9
9
$ git checkout -- orphan subtree
10
10
Switched to a new branch ' subtree'
11
11
$ rm file*
12
12
$ echo contents2 > file2
13
13
$ git add .
14
- $ git commit -m " add file2 (in subtree)" 1 > / dev/ null
14
+ $ git commit -m " add file2 (in subtree)" 1 >/ dev/ null
15
+ $ export SUBTREE_TIP= $ (git rev-parse HEAD)
15
16
16
17
Articially create a subtree merge
17
18
(merge commit has subtree files in subfolder but has subtree commit as a parent)
18
19
$ git checkout master
19
20
Switched to branch ' master'
20
- $ git merge subtree -- allow-unrelated-histories 1 > / dev/ null
21
+ $ git merge subtree -- allow-unrelated-histories 1 >/ dev/ null
21
22
$ mkdir subtree
22
23
$ git mv file2 subtree/
23
24
$ git add subtree
24
- $ git commit -a -- amend -m " subtree merge" 1 > / dev/ null
25
+ $ git commit -a -- amend -m " subtree merge" 1 >/ dev/ null
25
26
$ tree
26
27
.
27
28
| -- file1
@@ -37,11 +38,11 @@ Articially create a subtree merge
37
38
38
39
Change subtree file
39
40
$ echo more contents >> subtree/ file2
40
- $ git commit -a -m " subtree edit from main repo" 1 > / dev/ null
41
+ $ git commit -a -m " subtree edit from main repo" 1 >/ dev/ null
41
42
42
43
Rewrite the subtree part of the history
43
44
FIXME(RalfJung): if I use / subtree or subtree/ , the command still succeeds, but produces completely wrong output
44
- $ josh-filter -s : subtree_prefix= $ (git rev-parse subtree) ,subtree refs/ heads/ master -- update refs/ heads/ filtered
45
+ $ josh-filter -s : subtree_prefix= $ SUBTREE_TIP ,subtree refs/ heads/ master -- update refs/ heads/ filtered
45
46
\[4 \] : subtree_prefix= .* ,subtree (re )
46
47
47
48
$ git log -- graph -- pretty= % s refs/ heads/ filtered
@@ -63,3 +64,42 @@ Compare input and result. ^^2 is the 2nd parent of the first parent, i.e., the '
63
64
similarity index 100 %
64
65
rename from file2
65
66
rename to subtree/ file2
67
+
68
+ Extract the subtree history
69
+ $ josh-filter -s : subtree_prefix= $ SUBTREE_TIP ,subtree:/ subtree refs/ heads/ master -- update refs/ heads/ subtree
70
+ \[[0 -9]\] :/ subtree (re )
71
+ \[[0 -9]\] : subtree_prefix= .* ,subtree (re )
72
+ $ git checkout subtree
73
+ Switched to branch ' subtree'
74
+ $ cat file2
75
+ contents2
76
+ more contents
77
+
78
+ Work in the subtree, and sync that back.
79
+ $ echo even more contents >> file2
80
+ $ git commit -am " add even more content" 1 >/ dev/ null
81
+ $ josh-filter -s : subtree_prefix= $ SUBTREE_TIP ,subtree:/ subtree refs/ heads/ master -- update refs/ heads/ subtree -- reverse
82
+ \[[0 -9]\] :/ subtree (re )
83
+ \[[0 -9]\] : subtree_prefix= .* ,subtree (re )
84
+ $ git log -- graph -- pretty= % s refs/ heads/ master
85
+ * add even more content
86
+ * subtree edit from main repo
87
+ * subtree merge
88
+ | \
89
+ | * add file2 (in subtree)
90
+ * add file1
91
+ $ git ls-tree -- name-only -r refs/ heads/ master
92
+ file1
93
+ subtree/ file2
94
+ $ git checkout master
95
+ Switched to branch ' master'
96
+ $ cat subtree/ file2
97
+ contents2
98
+ more contents
99
+ even more contents
100
+
101
+ And then re-extract, which should re-construct the same subtree.
102
+ $ josh-filter -s : subtree_prefix= $ SUBTREE_TIP ,subtree:/ subtree refs/ heads/ master -- update refs/ heads/ subtree2
103
+ \[[0 -9]\] :/ subtree (re )
104
+ \[[0 -9]\] : subtree_prefix= .* ,subtree (re )
105
+ $ test $ (git rev-parse subtree) = $ (git rev-parse subtree2)
0 commit comments