Show More
@@ -122,10 +122,19 b' change, it is impossible in Mercurial to' | |||||
122 | a tag. Thus tagging a revision must be done as a second step. |
|
122 | a tag. Thus tagging a revision must be done as a second step. | |
123 |
|
123 | |||
124 |
|
124 | |||
|
125 | .Q. What if I want to just keep local tags? | |||
|
126 | ||||
|
127 | You can add a section called "[tags]" to your .hg/hgrc which contains | |||
|
128 | a list of tag = changeset ID pairs. Unlike traditional tags, these are | |||
|
129 | only visible in the local repository, but otherwise act just like | |||
|
130 | normal tags. | |||
|
131 | ||||
|
132 | ||||
125 | .Q. How do tags work with multiple heads? |
|
133 | .Q. How do tags work with multiple heads? | |
126 |
|
134 | |||
127 | The tags that are in effect at any given time are the tags specified |
|
135 | The tags that are in effect at any given time are the tags specified | |
128 | in each head, with heads closer to the tip taking precedence. |
|
136 | in each head, with heads closer to the tip taking precedence. Local | |
|
137 | tags override all other tags. | |||
129 |
|
138 | |||
130 |
|
139 | |||
131 | .Q. What are some best practices for distributed development with Mercurial? |
|
140 | .Q. What are some best practices for distributed development with Mercurial? | |
@@ -187,19 +196,82 b' Mercurial is primarily developed for UNI' | |||||
187 | may be present in ports. |
|
196 | may be present in ports. | |
188 |
|
197 | |||
189 |
|
198 | |||
190 | .Q. How does signing work? |
|
199 | .Q. How does Mercurial store its data? | |
|
200 | ||||
|
201 | The fundamental storage type in Mercurial is a "revlog". A revlog is | |||
|
202 | the set of all revisions of a named object. Each revision is either | |||
|
203 | stored compressed in its entirety or as a compressed binary delta | |||
|
204 | against the previous version. The decision of when to store a full | |||
|
205 | version is made based on how much data would be needed to reconstruct | |||
|
206 | the file. This lets us ensure that we never need to read huge amounts | |||
|
207 | of data to reconstruct a object, regardless of how many revisions of it | |||
|
208 | we store. | |||
|
209 | ||||
|
210 | In fact, we should always be able to do it with a single read, | |||
|
211 | provided we know when and where to read. This is where the index comes | |||
|
212 | in. Each revlog has an index containing a special hash (nodeid) of the | |||
|
213 | text, hashes for its parents, and where and how much of the revlog | |||
|
214 | data we need to read to reconstruct it. Thus, with one read of the | |||
|
215 | index and one read of the data, we can reconstruct any version in time | |||
|
216 | proportional to the object size. | |||
|
217 | ||||
|
218 | Similarly, revlogs and their indices are append-only. This means that | |||
|
219 | adding a new version is also O(1) seeks. | |||
|
220 | ||||
|
221 | Revlogs are used to represent all revisions of files, manifests, and | |||
|
222 | changesets. Compression for typical objects with lots of revisions can | |||
|
223 | range from 100 to 1 for things like project makefiles to over 2000 to | |||
|
224 | 1 for objects like the manifest. | |||
|
225 | ||||
|
226 | ||||
|
227 | .Q. How are manifests and changesets stored? | |||
|
228 | ||||
|
229 | A manifest is simply a list of all files in a given revision of a | |||
|
230 | project along with the nodeids of the corresponding file revisions. So | |||
|
231 | grabbing a given version of the project means simply looking up its | |||
|
232 | manifest and reconstruction all the file revisions pointed to by it. | |||
191 |
|
233 | |||
192 | Take a look at the hgeditor script for an example. The basic idea |
|
234 | A changeset is a list of all files changed in a check-in along with a | |
193 | is to sign the manifest ID inside that changelog entry. The manifest |
|
235 | change description and some metadata like user and date. It also | |
194 | ID is a recursive hash of all of the files in the system and their |
|
236 | contains a nodeid to the relevent revision of the manifest. | |
195 | complete history, and thus signing the manifest hash signs the entire |
|
237 | ||
196 | project to that point. |
|
238 | ||
|
239 | .Q. How do Mercurial hashes get calculated? | |||
|
240 | ||||
|
241 | Mercurial hashes both the contents of an object and the hash of its | |||
|
242 | parents to create an identifier that uniquely identifies an object's | |||
|
243 | contents and history. This greatly simplifies merging of histories | |||
|
244 | because it avoid graph cycles that can occur when a object is reverted | |||
|
245 | to an earlier state. | |||
|
246 | ||||
|
247 | All file revisions have an associated hash value. These are listed in | |||
|
248 | the manifest of a given project revision, and the manifest hash is | |||
|
249 | listed in the changeset. The changeset hash is again a hash of the | |||
|
250 | changeset contents and its parents, so it uniquely identifies the | |||
|
251 | entire history of the project to that point. | |||
|
252 | ||||
197 |
|
253 | |||
198 | More precisely: each file hash is an SHA1 hash of the contents of that |
|
254 | .Q. What checks are there on repository integrity? | |
199 | file and the hashes of its parent revisions. The manifest contains a |
|
255 | ||
200 | list of each file in the project along with its current file hash. |
|
256 | Every time a revlog object is retrieved, it is checked against its | |
201 | This manifest is hashed similarly to the file hashes, incorporating |
|
257 | hash for integrity. It is also incidentally doublechecked by the | |
202 | the hashes of the parent revisions. |
|
258 | Adler32 checksum used by the underlying zlib compression. | |
|
259 | ||||
|
260 | Running 'hg verify' decompresses and reconstitutes each revision of | |||
|
261 | each object in the repository and cross-checks all of the index | |||
|
262 | metadata with those contents. | |||
|
263 | ||||
|
264 | But this alone is not enough to ensure that someone hasn't tampered | |||
|
265 | with a repository. For that, you need cryptographic signing. | |||
|
266 | ||||
|
267 | ||||
|
268 | .Q. How does signing work with Mercurial? | |||
|
269 | ||||
|
270 | Take a look at the hgeditor script for an example. The basic idea is | |||
|
271 | to use GPG to sign the manifest ID inside that changelog entry. The | |||
|
272 | manifest ID is a recursive hash of all of the files in the system and | |||
|
273 | their complete history, and thus signing the manifest hash signs the | |||
|
274 | entire project contents. | |||
203 |
|
275 | |||
204 |
|
276 | |||
205 | .Q. What about hash collisions? What about weaknesses in SHA1? |
|
277 | .Q. What about hash collisions? What about weaknesses in SHA1? | |
@@ -213,3 +285,6 b' becomes a realistic concern.' | |||||
213 | Collisions with the "short hashes" are not a concern as they're always |
|
285 | Collisions with the "short hashes" are not a concern as they're always | |
214 | checked for ambiguity and are still long enough that they're not |
|
286 | checked for ambiguity and are still long enough that they're not | |
215 | likely to happen for reasonably-sized projects (< 1M changes). |
|
287 | likely to happen for reasonably-sized projects (< 1M changes). | |
|
288 | ||||
|
289 | ||||
|
290 |
General Comments 0
You need to be logged in to leave comments.
Login now