1 |
Hello, all. |
2 |
|
3 |
Following the late cleanup to git-r3, I'd like to discuss another idea |
4 |
that aims to most effectively satisfy the needs of various users, |
5 |
developers and packages. |
6 |
|
7 |
The idea is to provide three different clone types: mirror clone, single |
8 |
branch clone and shallow clone. User would select one of the types |
9 |
through make.conf (and per-package environment), while packages could |
10 |
specify a 'minimal' supported clone type. |
11 |
|
12 |
|
13 |
Mirror clone |
14 |
------------ |
15 |
|
16 |
- current git-r3 behavior (after the cleanup), |
17 |
|
18 |
- all branches and tags are updated from the remote repo (and pruned |
19 |
following removals in remote), |
20 |
|
21 |
- git notes are fetched, |
22 |
|
23 |
- EGIT_COMMIT can name any commit in any branch or tag, |
24 |
|
25 |
- best for developer use (ability to clone equivalent to remote) |
26 |
and local mirrors, |
27 |
|
28 |
- repositories with many outdated and diverged branches may be |
29 |
unnecessarily large. |
30 |
|
31 |
|
32 |
Single branch clone |
33 |
------------------- |
34 |
|
35 |
- git-2 eclass behavior, |
36 |
|
37 |
- only requested branch (or tag) is fetched, and tags on the commits |
38 |
fetched as part of the branch/tag history, |
39 |
|
40 |
- git notes are fetched, |
41 |
|
42 |
- EGIT_COMMIT can only name a commit in the fetched EGIT_BRANCH, |
43 |
|
44 |
- pruning unused branches/tags is hard (and possibly won't be |
45 |
implemented at first), |
46 |
|
47 |
- more efficient than the mirror mode, most likely future default. |
48 |
|
49 |
|
50 |
Shallow clone |
51 |
------------- |
52 |
|
53 |
- similar to old git-r3 behavior, |
54 |
|
55 |
- minimal number of objects from the requested branch (or tag) is |
56 |
fetched, |
57 |
|
58 |
- branch/tag history is not preserved, |
59 |
|
60 |
- git notes are not fetched, |
61 |
|
62 |
- EGIT_COMMIT can only name tags (using a hash auto-forces higher mode), |
63 |
|
64 |
- changing branches may be very inefficient (since it implies |
65 |
re-fetching all objects implied by --depth 1), |
66 |
|
67 |
- since the history is truncated, 'git describe' won't give pretty |
68 |
names, |
69 |
|
70 |
- most space-saving, intended for embedded and other special use cases, |
71 |
|
72 |
- does not guarantee repository consistency -- unsafe. |
73 |
|
74 |
|
75 |
Control variables |
76 |
----------------- |
77 |
|
78 |
I'm thinking of two control variables (better names appreciated): |
79 |
|
80 |
- EGIT_CLONE_MODE - set in make.conf by user to requested clone mode, |
81 |
|
82 |
- EGIT_MIN_CLONE_MODE - optionally set by ebuilds that require more. |
83 |
|
84 |
For example, if ebuilds sets EGIT_MIN_CLONE_MODE=single, and user sets |
85 |
EGIT_CLONE_MODE=shallow, this single ebuild will be fetched |
86 |
in single-branch mode. This can be used when build system operates |
87 |
on repo history and doesn't work without it. |
88 |
|
89 |
I can't think of a case when ebuild would need |
90 |
EGIT_MIN_CLODE_MODE=mirror. |
91 |
|
92 |
|
93 |
Mode upgrades and downgrades |
94 |
---------------------------- |
95 |
|
96 |
Mode is not associated persistently with a repository. Therefore, using |
97 |
a repository in a different mode than it was used before (e.g. due to |
98 |
different ebuild or user preference change) results in mixed-mode |
99 |
repository. |
100 |
|
101 |
When mirror or single-branch mode is used on a shallow repository, |
102 |
the repository is still marked 'shallow' even if the full history is |
103 |
available. I don't know if this wouldn't break some of 'git foo' uses |
104 |
in the checkout but that probably can't be predicted. Moreover, I don't |
105 |
know if it is safe to remove 'shallow' after doing full-fetch in mirror |
106 |
mode. |
107 |
|
108 |
When single-branch or shallow mode is used on a mirror-mode repository, |
109 |
only the requested branch/tag is updated. The repository may no longer |
110 |
be correctly synced to the remote. |
111 |
|
112 |
When shallow mode is used on *existing* branch or tag in a mirror-mode |
113 |
or single-branch repository, new commits are fetched as |
114 |
in single-branch mode. When shallow mode is used on *new* branch |
115 |
or tag, the commits are fetched with '--depth 1' and the clone is |
116 |
marked 'shallow'. |
117 |
|
118 |
|
119 |
Old branch/tag pruning |
120 |
---------------------- |
121 |
|
122 |
In mirror mode, pruning is pretty straightforward. Since all branches |
123 |
and tags are requested, 'git fetch --prune' removes the branches |
124 |
and tags that are removed upstream. The remaining branches and tags are |
125 |
expected. |
126 |
|
127 |
In single-branch and shallow mode, complete pruning is pretty much |
128 |
impossible. Upstream-removed branches and tags could be supposedly |
129 |
pruned using some explicit git-ls-remote magic. |
130 |
|
131 |
Removing 'old' branches (that is, no longer referenced by ebuilds) is |
132 |
pretty much impossible since one can't clearly determine whether |
133 |
the particular branch/tag will be used by other ebuilds :). This |
134 |
becomes especially blurry in case of mode switching. |
135 |
|
136 |
|
137 |
That's pretty much it. Most of the stuff I've tested proof-of-concept. |
138 |
It may not work as well in the actual eclass. Any thoughts? |
139 |
|
140 |
-- |
141 |
Best regards, |
142 |
Michał Górny |