{"thread":{"id":"6583","subject":"newbie questions about git design and features (some wrt hg)","startedAt":"2007-01-30T16:20:30Z","lastAt":"2007-02-03T21:45:33Z","messageCount":61,"participants":["Mike Coleman","Johannes Schindelin","Shawn O. Pearce","Jakub Narebski","Linus Torvalds","Junio C Hamano","Theodore Tso","Nicolas Pitre","Matt Mackall","Simon 'corecode' Schubert","Eric Wong","Mark Wooding","Brendan Cully","Giorgos Keramidas","Matthias Kestenholz"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"33045","messageId":"3c6c07c20701300820l42cfc8dbsb80393fc1469f667@mail.gmail.com","threadId":"6583","inReplyTo":null,"subject":"newbie questions about git design and features (some wrt hg)","fromName":"Mike Coleman","fromEmail":"tutufan@gmail.com","sentAt":"2007-01-30T16:20:30Z","receivedAt":"2007-01-30T16:20:30Z","isPatch":false,"sender":{"key":"tutufan@gmail.com","avatar":null},"body":"Hi,\n\nI recently decided to jump into the DVCS pool, and I've been studying\nwhat seem to me to be the two leading candidates--git and\nmercurial--to try to understand the differences between them in design\nand features.  I have some questions that I hope you can enlighten me\non.\n\n1.  As of today, is there any real safety concern with either tool's\nrepo format?  Is either tool significantly better in this regard?\n(Keith Packard's post hints at a problem here, but doesn't really make\nthe case.)\n\n2.  Does the git packed object format solve the performance problem\nalluded to in posts from a year or two ago?\n\n3.  Someone mentioned that git bisect can work between any two\ncommits, not necessarily just one that happens to be an ancestor of\nthe other.  This sounds really cool.  Can hg's bisect do this, too?\n\n4.  What is git's index good for?  I find that I like the idea of it,\nbut I'm not sure I could justify it's presence to someone else, as\nopposed to having it hidden in the way that hg's dircache (?) is.  Can\nanyone think of a good scenario where it's a pretty obvious benefit?\n\n5.  I think I read that there'd been just one incompatible change over\ntime in the git repo format.  What was it?\n\n6.  Does either tool use hard links?  This matters to me because I do\ndevelopment on a connected machine and a disconnected machine, using a\nusb drive to rsync between.  (Perhaps there'll be some way to transfer\nchanges using git or hg instead of rsync, but I haven't figured that\nout yet.)\n\n7.  I'm a fan of Python, and I'm really a fan of using high-level\nlanguages with performance-critical parts in a lower-level language,\nso in that regard, I really like hg's implementation.  If someone\nwanted to do it, is a Python clone of git conceivable?  Is there\nsomething about it that just requires C?\n\n8.  It feels like hg is not really comfortable with parallel\ndevelopment over time on different heads within a single repo.\nRather, it seems that multiple repos are supposed to be used for this.\n Does this lead to any problems?  For example, is it harder or\ndifferent to merge two heads if they're in different repo than if\nthey're in the same repo?\n\nThanks in advance,\nMike\n\n(I'll probably post this on the hg list as well.)\n"},{"id":"33049","messageId":"Pine.LNX.4.63.0701301725190.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"6583","inReplyTo":"3c6c07c20701300820l42cfc8dbsb80393fc1469f667@mail.gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-01-30T16:41:25Z","receivedAt":"2007-01-30T16:41:25Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 30 Jan 2007, Mike Coleman wrote:\n\n> I recently decided to jump into the DVCS pool, and I've been studying \n> what seem to me to be the two leading candidates--git and mercurial--to \n> try to understand the differences between them in design and features.  \n> I have some questions that I hope you can enlighten me on.\n\nI don't know Mercurial, but I know git pretty well.\n\n> 1.  As of today, is there any real safety concern with either tool's \n> repo format?  Is either tool significantly better in this regard? (Keith \n> Packard's post hints at a problem here, but doesn't really make the \n> case.)\n\nI can't remember any post hinting at a problem with regard to git's \nsafety.\n\nGit is very conservative about data. In fact, even if you fsck up royally, \nchances are very good that you recover without losing any data (which was \nstored in the repo).\n\nOf course, a \"rm -rf .\" will hurt in any case.\n\n> 2.  Does the git packed object format solve the performance problem \n> alluded to in posts from a year or two ago?\n\nI don't know what posts you mean.\n\nIn any case, if performance is an issue for you, you should keep your \nrepository packed (with new Git, you should call \"git gc\" every once in a \nwhile).\n\n> 3.  Someone mentioned that git bisect can work between any two commits, \n> not necessarily just one that happens to be an ancestor of the other.  \n> This sounds really cool.  Can hg's bisect do this, too?\n\nNo idea.\n\n> 4.  What is git's index good for?  I find that I like the idea of it, \n> but I'm not sure I could justify it's presence to someone else, as \n> opposed to having it hidden in the way that hg's dircache (?) is.  Can \n> anyone think of a good scenario where it's a pretty obvious benefit?\n\nGit's index is a staging area. Every VCS has it, but most hide it. One of \nthe moments where Git's index really shines is merge conflicts: you can \ninspect _just_ the conflicts by calling \"git diff\".\n\n> 5.  I think I read that there'd been just one incompatible change over \n> time in the git repo format.  What was it?\n\nObjects names were the hash of the _compressed_ contents. Now it's the \nuncompressed contents (which allows you to change the compression \nparameters without any hassle). This was _looong_ time ago.\n\n> 6.  Does either tool use hard links?  This matters to me because I do \n> development on a connected machine and a disconnected machine, using a \n> usb drive to rsync between.  (Perhaps there'll be some way to transfer \n> changes using git or hg instead of rsync, but I haven't figured that out \n> yet.)\n\nNo idea about Mercurial, but you can clone using hard links with the \n--local option.\n\nThere is still a script called git-relink, which can hard link \nunpacked objects of two object databases, but since we usually keep \neverything packed nowadays, I deem this obsolete.\n\nOf course, the better way is to use --shared with clone, so that a \n\"virtual hard link\" is set up: The alternates mechanism of Git is set up \nsuch that you reuse (even new) objects from the alternate repository.\n\n> 7.  I'm a fan of Python, and I'm really a fan of using high-level \n> languages with performance-critical parts in a lower-level language, so \n> in that regard, I really like hg's implementation.  If someone wanted to \n> do it, is a Python clone of git conceivable?  Is there something about \n> it that just requires C?\n\nI am not a fan of Python. I think that all the Perl hackers of old days \nmigrated to Python, because the code _looks_ nicer. But it's the same old \ncrap.\n\nThat said, nothing (least of which, me) hinders you reimplementing Git in \nPython. The performance critical parts are in the revision walking, and \nthe diff machinery.\n\nThe revision walking is not really reentrant (yet), so you would have to \nfix that up a little before being able to link it natively.\n\n> 8.  It feels like hg is not really comfortable with parallel development \n> over time on different heads within a single repo. Rather, it seems that \n> multiple repos are supposed to be used for this. Does this lead to any \n> problems?\n\nUsually not. I do it all the time (keep the branches in the same repo).\n\n> For example, is it harder or different to merge two heads if they're in \n> different repo than if they're in the same repo?\n\nYou _have_ to fetch it to merge it (this operation, fetch & merge, is \ncalled pull with Git), but there is no difference if the branch \nto-be-merged is local or remote. In fact, branches are not supposed to be \n\"local\" or \"remote\". You can _have_ them where you want. And you can tell \nif two branches are identical by the object name of their tip.\n\nHth,\nDscho\n"},{"id":"33051","messageId":"20070130165548.GF25950@spearce.org","threadId":"6583","inReplyTo":"3c6c07c20701300820l42cfc8dbsb80393fc1469f667@mail.gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-30T16:55:48Z","receivedAt":"2007-01-30T16:55:48Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Mike Coleman <tutufan@gmail.com> wrote:\n> 1.  As of today, is there any real safety concern with either tool's\n> repo format?  Is either tool significantly better in this regard?\n> (Keith Packard's post hints at a problem here, but doesn't really make\n> the case.)\n\nI think the Git format is tighter in terms of compression,\nand simpler in terms of understanding and writing code.  I have\npersonally written the code to read and write the Git repository\nformat in both C and Java, and in both cases it falls out in just\na few hundred lines of code (assuming you have libz handy to do\nthe compression/decompression for you).\n\nThe Git format is completely safe with regards to parallel\nmodification of a repository, which is good for shared repositories\nthat might have multiple people pushing into it at once.\n\nGit's format is also safe with regards to *any* update.\nYou literally cannot destroy the repository during an update.\nIts impossible.  You'd have to physically destroy the storage device.\n(OK, that's overstating it a bit, but it is really hard.)\n\nThe point Keith was making was the Git format is \"add-only\".\nOnce something has been stored, we NEVER modify it again.  This\nbypasses any sort of possible problems that can occur with partial\nmodifications caused by a process aborting in the middle of a change.\n\nI think hg modifies files as it goes, which could cause some issues\nwhen a writer is aborted.  I'm sure they have thought about the\nproblem and tried to make it safe, but there isn't anything safer\nthan just leaving the damn thing alone.  :)\n \n> 2.  Does the git packed object format solve the performance problem\n> alluded to in posts from a year or two ago?\n\nYes.  By a huge margin.  Git's *fast*.  Ignore anything from a year\nor two ago.\n \n> 3.  Someone mentioned that git bisect can work between any two\n> commits, not necessarily just one that happens to be an ancestor of\n> the other.  This sounds really cool.  Can hg's bisect do this, too?\n\nNo clue.\n \n> 4.  What is git's index good for?  I find that I like the idea of it,\n> but I'm not sure I could justify it's presence to someone else, as\n> opposed to having it hidden in the way that hg's dircache (?) is.  Can\n> anyone think of a good scenario where it's a pretty obvious benefit?\n\nIts a good way to stage the stuff in your next commit.  By that I\nmean you edit some code.  Then you look at what differs between the\nindex and your working directory.  You decide \"this hunk is good, it\npassed the tests, I want to commit that, so toss it into the index\".\nNow that hunk isn't different anymore.\n\nWhen it comes time to commit, all of your already reviewed stuff is\nstaged in the index.  You just need to issue a commit and supply\nthe message.  But you can leave modified stuff in the working\ndirectory, even for files that were alerady updated in the index.\n\nThis really helps during a merge.  Only the stuff which Git could\nnot merge for you is seen as different between the index and the\nworking directory; all of the stuff that Git merged for you is\nalready staged in the index.  So you can focus on the conflicts,\nand stage their resolutions into the index as you go.  This makes\nit easier to work through larger merges where more than 1 or 2\nfiles contains conflicts.\n\n> 5.  I think I read that there'd been just one incompatible change over\n> time in the git repo format.  What was it?\n\nA LONG time ago, like in the very first version Linus offered out\nto the public, we computed the identity of an object using the\nSHA-1 hash of the *compressed* data.  This is sensitive to the\ncompression settings used, and was not the best idea as a result.\n\nIt was very quickly changed to compute the identity of the object\nusing the SHA-1 has of the raw (user) data, removing any dependence\non the compression routine to always yield the same result for the\nsame input.\n\nWe haven't had a change since then.  We have added some new\ncompression options which are just that, options.  If you use them\nolder Git binaries won't necessarily recognize the repository data,\nbut these are off by default and can be enabled on a per-repository\nbasis.  E.g. if you are only using newer Git on a given system you\ncan enable the newer compression features on all of the repositories\non that system.\n \n> 6.  Does either tool use hard links?  This matters to me because I do\n> development on a connected machine and a disconnected machine, using a\n> usb drive to rsync between.  (Perhaps there'll be some way to transfer\n> changes using git or hg instead of rsync, but I haven't figured that\n> out yet.)\n\nGit can use hardlinks if you ask it to.  We only use them for the\nrepository files, not for the user's actual source files.\n\nGit has its own native transport (git-push, git-fetch) which can\nmove data between two Git repositories via local filesystem access,\nSSH, HTTP, FTP, and rsync (latter two are read-only transports).\n \n> 7.  I'm a fan of Python, and I'm really a fan of using high-level\n> languages with performance-critical parts in a lower-level language,\n> so in that regard, I really like hg's implementation.  If someone\n> wanted to do it, is a Python clone of git conceivable?  Is there\n> something about it that just requires C?\n\nYes, a Python clone of Git is conceivable.  Indeed, there is a\npure Java clone in process (jgit) for an Eclipse plugin (egit).\nIf you wanted to rewrite Git in Python, knock yourself out.\nBut we've ported all of our Python to C, as its just faster.\n \n> 8.  It feels like hg is not really comfortable with parallel\n> development over time on different heads within a single repo.\n> Rather, it seems that multiple repos are supposed to be used for this.\n> Does this lead to any problems?  For example, is it harder or\n> different to merge two heads if they're in different repo than if\n> they're in the same repo?\n\nNo clue.  I know multiple heads in one Git repository works\n*awesome*.  Especially on large repositories (>10k files) as the time\nrequired to start a new branch is only the time needed to update the\nfiles in the working directory which don't have the correct version.\nUsually that's a small percentage (<200) of the files and thus its\nvery fast to switch to a new branch of development, and switch back.\n\nOn a decent UNIX system (and my Mac OS X PowerBook doesn't really\ncount) flipping branches in git-gui is almost immediate.  You pick\nthe branch in the menu and *wham* its switched.  And that's my\nPowerBook, which as I said, doesn't quite count as good UNIX\nsystem...\n\n-- \nShawn.\n"},{"id":"33055","messageId":"epo03h$2nc$1@sea.gmane.org","threadId":"6583","inReplyTo":"3c6c07c20701300820l42cfc8dbsb80393fc1469f667@mail.gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-01-30T17:44:31Z","receivedAt":"2007-01-30T17:44:31Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"[Cc: git@vger.kernel.org]\n[Followup-To: git@vger.kernel.org aka gmane.comp.version-control.git]\n\nMike Coleman wrote:\n\n> I recently decided to jump into the DVCS pool, and I've been studying\n> what seem to me to be the two leading candidates--git and\n> mercurial--to try to understand the differences between them in design\n> and features.  I have some questions that I hope you can enlighten me\n> on.\n> \n> 1.  As of today, is there any real safety concern with either tool's\n> repo format?  Is either tool significantly better in this regard?\n> (Keith Packard's post hints at a problem here, but doesn't really make\n> the case.)\n\nI don't know if Mercurial is safe with respect to interrupting in\nthe midle of update. Git is safe in that regard; the only unsafe\ncommand is git-prune (and it is explicitely as such marked in\ndocumentation); there were some attempts lately about making it safer.\n \n> 2.  Does the git packed object format solve the performance problem\n> alluded to in posts from a year or two ago?\n\nIf it was I/O performance problem, then packed objects format and\nto lesser extent (important only if you have large number of tags\nor branches) packed refs format, should solve it.\n\nSee http://git.or.cz/gitwiki/GitBenchmarks (most probably biased).\n\n> 3.  Someone mentioned that git bisect can work between any two\n> commits, not necessarily just one that happens to be an ancestor of\n> the other.  This sounds really cool.  Can hg's bisect do this, too?\n\nThe very idea of git bisect was for it to work with nonlinear history.\nOtherwise it wouldn't be really necessary.\n\ngit-bisect(1) mentions git-rev-list --bisect option, and in description\nof --bisect in git-rev-list(1) we have:\n\n        Limit output to the one  commit  object  which  is  roughly  halfway\n        between the included and excluded commits. Thus, if\n\n                $ git-rev-list --bisect foo ^bar ^baz\n\n        outputs 'midpoint', the output of the two commands\n\n                $ git-rev-list foo ^midpoint\n                $ git-rev-list midpoint ^bar ^baz\n\n        would be of roughly the same length. Finding the change which intro-\n        duces a regression is thus reduced to a  binary  search:  repeatedly\n        generate  and  test  new  'midpoint's  until  the commit chain is of\n        length one.\n\n(where \"git rev-list foo ^bar\" means listing all commits reachable from\ncommit, tag or branch 'foo' which are not reachable from 'bar').\n\n> 4.  What is git's index good for?  I find that I like the idea of it,\n> but I'm not sure I could justify it's presence to someone else, as\n> opposed to having it hidden in the way that hg's dircache (?) is.  Can\n> anyone think of a good scenario where it's a pretty obvious benefit?\n\nGit index is used to stage commits, i.e. create it part by part (create\nsome changes, view diff of those changes, save those changes to index,\ncreate some new changes, view diff of new changes, etc.). And it is very\nuseful in resolving merges and merge conflicts (you can view diff only\nof the conflicted part). Also it makes add / remove operations easier\nto understand. \n\nIt also allows for some tricks like \"SCM remove all files\nknown to SCM, which are missing in working repository\", or \"make SCM\nthink that all files are newer when importing from tar file\".\n \n> 5.  I think I read that there'd been just one incompatible change over\n> time in the git repo format.  What was it?\n\nIf you are referring to the change that sha-1 used to be of compressed\ncontents, it was IIRC before first public release.\n \n> 6.  Does either tool use hard links?  This matters to me because I do\n> development on a connected machine and a disconnected machine, using a\n> usb drive to rsync between.  (Perhaps there'll be some way to transfer\n> changes using git or hg instead of rsync, but I haven't figured that\n> out yet.)\n\nGit can use hard links (git clone --local, git relink) but does not need\nto. If you have hardlinks under version control, git does not checkout\nthem as hardlinks.\n\n> 7.  I'm a fan of Python, and I'm really a fan of using high-level\n> languages with performance-critical parts in a lower-level language,\n> so in that regard, I really like hg's implementation.  If someone\n> wanted to do it, is a Python clone of git conceivable?  Is there\n> something about it that just requires C?\n\nC is for performance. Git is not libified, and it would be hard to get\nit fully (or at least most important parts) libified.\n\n> 8.  It feels like hg is not really comfortable with parallel\n> development over time on different heads within a single repo.\n> Rather, it seems that multiple repos are supposed to be used for this.\n> Does this lead to any problems?  For example, is it harder or\n> different to merge two heads if they're in different repo than if\n> they're in the same repo?\n\nIn git if you want to merge two heads in different repos, you in fact\nfirst download (fetch) the objects from other repo, then merge two local\nhead one of which can be temporary (FETCH_HEAD) although usually we use\nlocal branch (so called tracking branch) to always refer to downloaded\nobjects from other repo.\n\n> (I'll probably post this on the hg list as well.)\n\nI'm not sure if Mercurial mailing list is not subscribe-to-post,\nunfortunately...\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"33057","messageId":"Pine.LNX.4.64.0701300906260.3611@woody.linux-foundation.org","threadId":"6583","inReplyTo":"3c6c07c20701300820l42cfc8dbsb80393fc1469f667@mail.gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-01-30T18:06:08Z","receivedAt":"2007-01-30T18:06:08Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 30 Jan 2007, Mike Coleman wrote:\n> \n> 1.  As of today, is there any real safety concern with either tool's\n> repo format?  Is either tool significantly better in this regard?\n> (Keith Packard's post hints at a problem here, but doesn't really make\n> the case.)\n\nI think Keith was nervous about hg, because hg\n (a) has changed repo formats a few times and was talking about changing \n     it again (but since I don't follow hg very closely, I don't know if \n     that has happened, will happen, or was shelved)\n (b) modifies data in-place.\n\nGit doesn't really do either. Git has extended the repository format a few \ntimes (notably pack-files), but apart from a *really* early change at the \nvery beginning of development, the git repo format is identical today to \nwhat it was originally, and you can read old repositories without any \nconverision what-so-ever.\n\nAlso, the git repository format is (and has always been) \"stable\" in \nanother sense: we never *ever* re-write any old data. Even when we \nre-pack, we write a totally new copy, and while you'd often then get rid \nof duplicates afterwards, the operation is fundamentally safer that way.\n\n> 2.  Does the git packed object format solve the performance problem\n> alluded to in posts from a year or two ago?\n\nIf you mean the original discussions in the first few months of git \ndevelopment, then yes. People used to worry that git's unpacked format was \nnot only slow, but also would chew up disk like mad. Both were true, and \nyes, both were solved by the packed format (to the point where I think git \nuses the *least* amount of disk space of any SCM ever made ;)\n\nHOWEVER. Git definitely has a different \"performance profile\" than many \nother SCM's do, and it's something worth keeping in mind. That has less to \ndo with the pack-files than just very fundamental git design.\n\nIn particular, *every* other SCM I am aware of does history on a per-file \nbasis. Git very fundamentally does not. This means that while git \noutperforms just about anything else, if you expect \"individual file \nhistory\" to be any faster than \"whole repository history\", you're simply \ngoing to be in for a surprise. It very fundamentally isn't. \n\nWe had this particular performance \"anomaly\" be discussed just the other \nweek. People seem to be so used to the \"file ID\" mentality that has its \nroots in RCS etc, that they expect \"git log <filename>\" to somehow be \nfaster than \"git log\". In git, that's simply not true. History is *always* \nseen as a \"full repository history\". There simply isn't anything else.\n\nI personally don't see this as a \"problem\", but it definitely is \n*different*. And it causes a different performance profile for various \noperations than you'd see with other SCM's.\n\n[ The reason I don't think this is a problem is because it's partly what \n  makes whole-repository operations like \"merge\" so fast. But it's also \n  the thing that causes git to very naturally not care about single files, \n  and anything you can do with a single file you can basically do with an \n  arbitrary set of files or directories. Which is *very* powerful, and as \n  far as I know, no other SCM can effectively do that at all.\n\n  As a top-level maintainer of a project with tens of thousands of files, \n  I end up almost never looking at individual files: I look at collections \n  of files. And that's where git shines, and almost everybody else falls \n  flat on their face. But if you have the \"single-file\" mentality, you \n  will find operations that you think git does badly. ]\n\n> 3.  Someone mentioned that git bisect can work between any two\n> commits, not necessarily just one that happens to be an ancestor of\n> the other.  This sounds really cool.  Can hg's bisect do this, too?\n\nI suspect it can - as far as I know, the whole \"bisect\" thing originated \nwith git, and hg picked up the idea from that. You'd have to be really \nstupid (and/or have a horrible repo format) to not be able to do multiple \nunrelated commits.\n\nHOWEVER! One thing that may make it less useful in hg is that last I \nheard, hg didn't do multiple independent branches in the same repository. \nSo some of the more useful usage schenarios may simply not be viable in hg \nat all (ie you'd have to merge in order to bring the two unrelated commits \ninto the same hg repository, and merging may not always be possible).\n\nSo with git, you can say \"that branch is good, this branch is bad, what \ncaused the regression?\" by using \"git bisect\". In hg, I'm not sure that \nworks, simply because of the weakness of branches. But you'd have to ask \nthe hg lists. They do have *some* concept of branches within a repo, so it \nmay well be that it all works out.\n\n> 4.  What is git's index good for?  I find that I like the idea of it,\n> but I'm not sure I could justify it's presence to someone else, as\n> opposed to having it hidden in the way that hg's dircache (?) is.  Can\n> anyone think of a good scenario where it's a pretty obvious benefit?\n\nIt's a huge deal during merging with conflicts.\n\nDuring merging, the index is the part that shows you what the conflicts \nare, and also where you mark any conflict resolution while the working \ntree is still not fully resolved. However, it's kind of hard to show the \n\"obvious benefit\" without actually showing an example of a real (and \ncomplex) merge conflict, and I'm way too lazy for that.\n\nIt has advantages in many other situations too, but they are more subtle. \nOne of the things _I_ consider to be an advantage (but which confuses some \npeople because it's also another thing that makes git different from many \nother SCM systems) is that the index is also where you \"prepare\" your work \nfor committing, and this is especially obvious when adding new files.\n\nEvery single SCM has *some* kind of an index, even if it's as simple as \njust the CVS \"list of files I know about\". So in CVS, the \"index\" is \nreally just the \"CVS/Entries\" list. You really can think of the git index \nas just a \"CVS/Entries\" kind of thing, done right.\n\nSo what does \"done right\" mean? It means that the git index not only lists \nthe filenames, it lists their *contents* and status too. That means that \nwhen you do a \"git add\", you don't just add a filename to the list of \nfiles you know about, you literally add the *content*.\n\nThe reason this is important is that this is fundmanetally how git works: \ngit doesn't actually really *ever* work with filenames at any stage all, \ngit either works with \"content\" (which obviously includes the notion of a \nfilename, but it is also the mode of the file and the content of the \nfile), and git also has a notion of \"pathname limiter\", which basically \nworks on a repository \"tree\" level, and limits the content to just a \nsubset of the whole tree.\n\nSo the \"index\" is very much part of this - it's just another portion of \nthe fact that git always tracks *contents* and never tracks \"file ID's\".\n\nSo in CVS (or SVN), when you do a \"cvs add\", you really don't add any \ncontent to the repository, you are really adding a new \"file ID\" to the \nlist of files that CVS/SVN tracks. In git, when you do \"git add\", you are \nreally adding content, but that also means that the index - the \n\"CVS/Entries\" replacement - has to be able to track things differently.\n\nAnyway, if you come from CVS, and have worked with it intimately enough \nthat you know how things like CVS/Entries work, it should actually be \nfairly easy to pick up on the git index. You just need to mentally realize \n\"oh, it contains the contents, file mode and merge conflict state too!\"\n\n> 5.  I think I read that there'd been just one incompatible change over\n> time in the git repo format.  What was it?\n\nThe original git object naming was to first compress the object, and then \ncalculate the SHA1 of the compressed end result. That was stupid, stupid, \nand I admit it.  I switched it around.\n\nHowever, to get some notion of how early this was, the first git release \nwas done on April 7, 2005. The change-over to switch the compression and \nSHA-1 hashing around was done April 20, 2005. There was an additional \nfix to do the date handling more sanely, April 23, 2005. The format has \nbeen stable since.\n\nSo yes, there has been one real format change, and it happened two weeks \ninto development, long before git was really usable by mere mortals at \nall.\n\nAfter that, we have added capabilities to the the database (notably, the \npacked files, and a new simplified loose object format), but as far as I \nknow, current git will happily read any git archive written after April \n23rd, 2005. With no data conversion necessary.\n\nGoing the other way is obviously not always possible. If you get a git \nfrom May of 2005, and try to use it on an archive that uses pack-files, it \nobviously will *not* work. But even there, we've been very careful, and \nunless you set some specific options in your config file or do things like \nexplicitly pack your branch head/tag references, fairly old versions of \ngit will happily read even new archives.\n\n> 6.  Does either tool use hard links?  This matters to me because I do\n> development on a connected machine and a disconnected machine, using a\n> usb drive to rsync between.  (Perhaps there'll be some way to transfer\n> changes using git or hg instead of rsync, but I haven't figured that\n> out yet.)\n\nI don't know about hg (but will assume not). Git generally does not, but \ndoesn't mind them either if you have them in your working tree.\n\nAnd yes, there are ways to transfer using git natively, and they tend to \nbe a lot more useful and safe than rsync.\n\n> 7.  I'm a fan of Python, and I'm really a fan of using high-level\n> languages with performance-critical parts in a lower-level language,\n> so in that regard, I really like hg's implementation.  If someone\n> wanted to do it, is a Python clone of git conceivable?  Is there\n> something about it that just requires C?\n\nIt doesn't \"require\" C in the sense that the object format is actually \nfairly simple, and you could do things natively in python if you *really* \nwanted. That said, the whole approach of git has always been to write the \n\"core\" core in C, and just make the thing very scriptable. \n\nSome things simply are not sensible to do in a slow interpreted language. \nThings like generating diffs (another name for \"comparing two trees\") is \nfundamnetally much too performance-sensitive for anything but a serious \nsystem language. You need a compiled language with a good compiler, no \n\"byte code pre-compilers\" need apply. Same goes for the \"view repository \nthrough a filename filter\" thing.\n\nWe used to have our standard \"merge\" function written in python, but \nmainly because it was our *only* python dependency, it actually got \nrewritten in C (also, people - including me - really expect to merge two \nbranches with 20+ _thousand_ files in them in less than a second, so that \nmay explain another reason why the merge got rewritten).\n\n> 8.  It feels like hg is not really comfortable with parallel\n> development over time on different heads within a single repo.\n> Rather, it seems that multiple repos are supposed to be used for this.\n> Does this lead to any problems?  For example, is it harder or\n> different to merge two heads if they're in different repo than if\n> they're in the same repo?\n\nThat is my understanding too, but I've not followed hg actively.\n\nThe git branching model really is superior. It might take a while to get \nused to it (it took _me_ a while to get used to it ;), but once you do, \neverybody else so *obviously* does it so horribly badly that it's not even \nfunny.\n\nSo the whole \"multiple branches in the same repo\" thing really shines in \ngit. SCM's like SVN *claim* that they do multiple branches, but they \nreally don't. They are just confused.\n\n\t\tLinus\n"},{"id":"33059","messageId":"7v8xfkz8oj.fsf@assigned-by-dhcp.cox.net","threadId":"6583","inReplyTo":"3c6c07c20701300820l42cfc8dbsb80393fc1469f667@mail.gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-30T18:11:24Z","receivedAt":"2007-01-30T18:11:24Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Mike Coleman\" <tutufan@gmail.com> writes:\n\n> Hi,\n\nHi, Mike.\n\nI won't go into \"comparison\", and I know some people will fill\nthe details in other things\n\n> 5.  I think I read that there'd been just one incompatible change over\n> time in the git repo format.  What was it?\n\nThere actually were a few incompatible ones but they were only\nduring the first few weeks of life (the beginning of time is Apr\n7th, 2005):\n\n - The tree object was originally a flat \"manifest\" but was\n   converted to hierarchy of trees (Apr 10th, 2005)\n\n - The metainformation directory was originally called .dircache,\n   but renamedto \".git\" (Apr 11th, 2005)\n\n - The order of compression and hashing was swapped and older\n   objects needed conversion (Apr 20, 2005)\n"},{"id":"33078","messageId":"Pine.LNX.4.64.0701301135290.3611@woody.linux-foundation.org","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0701300906260.3611@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-01-30T19:37:33Z","receivedAt":"2007-01-30T19:37:33Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 30 Jan 2007, Linus Torvalds wrote:\n> \n> We had this particular performance \"anomaly\" be discussed just the other \n> week. People seem to be so used to the \"file ID\" mentality that has its \n> roots in RCS etc, that they expect \"git log <filename>\" to somehow be \n> faster than \"git log\". In git, that's simply not true. History is *always* \n> seen as a \"full repository history\". There simply isn't anything else.\n\nSide note: some people have talked about changing this by generating some \nkind of per-filename cache to make logging ops have an \"accelerated\" mode \nfor the trivial cases.\n\nSo maybe git at some future date will have a special-case for a single \nfilename, but that's definitely not the case today.\n\n\t\t\tLinus\n"},{"id":"33103","messageId":"20070131015555.GA1944@thunk.org","threadId":"6583","inReplyTo":"20070130165548.GF25950@spearce.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Theodore Tso","fromEmail":"tytso@mit.edu","sentAt":"2007-01-31T01:55:55Z","receivedAt":"2007-01-31T01:55:55Z","isPatch":false,"sender":{"key":"tytso@mit.edu","avatar":"https://avatars.githubusercontent.com/u/51416?v=4"},"body":"On Tue, Jan 30, 2007 at 11:55:48AM -0500, Shawn O. Pearce wrote:\n> I think hg modifies files as it goes, which could cause some issues\n> when a writer is aborted.  I'm sure they have thought about the\n> problem and tried to make it safe, but there isn't anything safer\n> than just leaving the damn thing alone.  :)\n\nTo be fair hg modifies files using O_APPEND only.  That isn't quite as\nsafe as \"only creating new files\", but it is relatively safe.\n\nOne other interesting point which came as a surprise to me is the size\nof the repositories.  It used to be that git was much more inefficient\nat storing files that Mercurial.  However, what pack files, and\ndeltas, I'm pleased to say a mercurial repository with all of\ne2fsprogs' history is 20 megs, while a git repository with the same\nhistory is 11 megs.   \n\n(BTW, I've been doing some hacking of Stelian Pop's hg2git.py in my\nspare time.  Most of the changes are e2fsprogs specific, but if anyone\nelse is hacking on it, I'd love to compare notes.  I have some vague\nthoughts about making hg2git to be bidirectional, but I probably won't\nhave time to implement it.)\n\n> Yes.  By a huge margin.  Git's *fast*.  Ignore anything from a year\n> or two ago.\n\nI'd go even further.  You probably want to use the latest git 1.5.0 rc\nrelease, or final, since it has been a lot uf usability and\ndocumentation improvements over previous git releases.\n\n> > 4.  What is git's index good for?  I find that I like the idea of it,\n> > but I'm not sure I could justify it's presence to someone else, as\n> > opposed to having it hidden in the way that hg's dircache (?) is.  Can\n> > anyone think of a good scenario where it's a pretty obvious benefit?\n\nIn git 1.5.0 it's a lot easier for users to not have to worry about\nthe index if they don't want to.  It's not quite so much in the user's\nface, although there is still improvement to be had, especially in the\ngit documentation.  There is a git user's manual being prepared (that\nI think will be in 1.5.0, hopefully) that is much better than \"man git\".\n\n> This really helps during a merge.  Only the stuff which Git could\n> not merge for you is seen as different between the index and the\n> working directory; all of the stuff that Git merged for you is\n> already staged in the index.  So you can focus on the conflicts,\n> and stage their resolutions into the index as you go.  This makes\n> it easier to work through larger merges where more than 1 or 2\n> files contains conflicts.\n\nThe flip side of this is that mercurial as much better integration\nwith graphical merge tools, which git doesn't have by default (yet).\n\n> > 8.  It feels like hg is not really comfortable with parallel\n> > development over time on different heads within a single repo.\n> > Rather, it seems that multiple repos are supposed to be used for this.\n> > Does this lead to any problems?  For example, is it harder or\n> > different to merge two heads if they're in different repo than if\n> > they're in the same repo?\n\nhg has only recently added support for development on different heads\nwithin the same repo.  So it's just more immature there.  Presumably\nover time it will get better.  Most poeple who use use hg don't use a\nlot of different branches, for things like topic branches, for\nexample.  If you prefer to use that style of interaction, git is going\nto be a much better choice for you.\n\nRegards,\n\n\t\t\t\t\t\t\t- Ted\n"},{"id":"33105","messageId":"3c6c07c20701301938u4d1503a2m3e0af51121b8e6db@mail.gmail.com","threadId":"6583","inReplyTo":"7v8xfkz8oj.fsf@assigned-by-dhcp.cox.net","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Mike Coleman","fromEmail":"tutufan@gmail.com","sentAt":"2007-01-31T03:38:10Z","receivedAt":"2007-01-31T03:38:10Z","isPatch":false,"sender":{"key":"tutufan@gmail.com","avatar":null},"body":"Thanks for all of your replies--this information is very helpful.\nThough both hg and git look good, I will probably try git first,\npartly because it seems the most interesting.  It feels like fertile\nground for experiments, and I suspect someone will think of some\nsurprising application for it.  (Also, I had the privilege of working\nwith Junio in a past life, and I consider his involvement a good\nportent.)\n\nThis mercurial list post by Ted Tso was also useful:\n\n    http://www.selenic.com/pipermail/mercurial/2007-January/012039.html\n\nRegarding a Python (or other interpreted language) implementation, the\nmost obvious practical benefit would be an easy win32 port.  Not that\nI'd ever choose to develop there, but it removes its lack as an\nobjection in some organizational settings (such as mine).  Someone\nmentioned a Java port--that'd cover that base quite well.\n\nAs for performance, my thinking was that since hg is implemented\napparently almost entirely in Python, and has (again apparently)\ngenerally acceptable performance, this suggested that much of the\nproblem might be I/O-bound enough that language efficiency might not\nmatter so much.\n\nAside: The program for which I'm considering trying git does mass spec\nprotein identification and has (in the general case) exponential\nruntime, all of it CPU.  Run times on a 500-node cluster start at two\nhours and go up rapidly.  You might think at first that this wouldn't\nbe a good candidate for Python, but so far this looks to be incorrect.\n The simple reason: asymptotically, all of the run time happens in\nabout four functions.  Given that, and friendly constants, what was\nabout 15K (*) lines of C++ has turned into somewhat less than 1K lines\nof C++ and 1K lines of Python--it's difficult to gauge because so many\nnew features have been added.  Somewhat ironically, the worst\nperformance issue seems to be C++'s obscure (to me) object\nconstruction costs--I may end up just switching the C++ part to C.\n\nThere are many axes of design to be considered, of course, but the\nmoral I took away from that is that better than asking \"Does this\nprogram have to be really fast?\", one should ask \"How many lines of\nthis program could run 20x slower (than C) without significantly\naffecting overall performance?\"  If the answer is 80%, it might be\nworth thinking about.  Skepticism is always in order, of course.\n\nMike\n\n(*) via David Wheeler's sloccount\n"},{"id":"33107","messageId":"Pine.LNX.4.64.0701302029460.3611@woody.linux-foundation.org","threadId":"6583","inReplyTo":"3c6c07c20701301938u4d1503a2m3e0af51121b8e6db@mail.gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-01-31T04:35:02Z","receivedAt":"2007-01-31T04:35:02Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 30 Jan 2007, Mike Coleman wrote:\n> \n> As for performance, my thinking was that since hg is implemented\n> apparently almost entirely in Python, and has (again apparently)\n> generally acceptable performance, this suggested that much of the\n> problem might be I/O-bound enough that language efficiency might not\n> matter so much.\n\nNote that git actually implements a lot more than hg does.\n\nhg depends on external programs (almost uniformly written in C) to do the \nactual diff generation, 3-way merging etc. \n\nGit actually ends up doing all of those internally, and minimizes external \ndependencies that way. More importantly, perhaps, it allows us to do a \nbetter job, faster. The early example of this is patch application, where \ngit supports a much nicer patch format that can express renames etc in the \npatch.\n\nBut I'll admit - my main reason going with C is (a) it's what I know and \n(b) I absolutely _hate_ being constrained by the language. The great thing \nabout C (still) is that you can do *anything* in it. You're literally \nlimited by hardware, and by your own abilities. Nothing else.\n\n\t\t\tLinus\n"},{"id":"33109","messageId":"7vodofx06s.fsf@assigned-by-dhcp.cox.net","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0701302029460.3611@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-31T04:57:47Z","receivedAt":"2007-01-31T04:57:47Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> But I'll admit - my main reason going with C is (a) it's what I know and \n> (b) I absolutely _hate_ being constrained by the language. The great thing \n> about C (still) is that you can do *anything* in it. You're literally \n> limited by hardware, and by your own abilities. Nothing else.\n>\n> \t\t\tLinus\n\nWell, if you count \"time\" as part of your own ability then that\nis true.  Some things are too cumbersome and not performance\ncritical enough to do in C.\n"},{"id":"33112","messageId":"3c6c07c20701302311w38b3dbdfs553c089505516fd0@mail.gmail.com","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0701302029460.3611@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Mike Coleman","fromEmail":"tutufan@gmail.com","sentAt":"2007-01-31T07:11:37Z","receivedAt":"2007-01-31T07:11:37Z","isPatch":false,"sender":{"key":"tutufan@gmail.com","avatar":null},"body":"On 1/30/07, Linus Torvalds <torvalds@linux-foundation.org> wrote:\n> But I'll admit - my main reason going with C is (a) it's what I know and\n> (b) I absolutely _hate_ being constrained by the language. The great thing\n> about C (still) is that you can do *anything* in it. You're literally\n> limited by hardware, and by your own abilities. Nothing else.\n\nI have a lot of sympathy for this way of thinking, and maybe even a\nlittle envy of people who've found worthy things to do at this level.\n\nBut I'm also very lazy (and probably not that talented).  So, I count\nmyself lucky that I've found a niche in the age of Python/Ruby/etc and\nMoore's Law.  I turn programs around quickly, telling users \"come back\nif you need it to go faster\", at which point I would profile and drop\nto C, or even assembler.  But they never do--they just want the next\nprogram.\n\nMike\n"},{"id":"33120","messageId":"eppshi$1l4$1@sea.gmane.org","threadId":"6583","inReplyTo":"20070131015555.GA1944@thunk.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-01-31T10:56:01Z","receivedAt":"2007-01-31T10:56:01Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Theodore Tso wrote:\n\n> On Tue, Jan 30, 2007 at 11:55:48AM -0500, Shawn O. Pearce wrote:\n>> I think hg modifies files as it goes, which could cause some issues\n>> when a writer is aborted.  I'm sure they have thought about the\n>> problem and tried to make it safe, but there isn't anything safer\n>> than just leaving the damn thing alone.  :)\n> \n> To be fair hg modifies files using O_APPEND only.  That isn't quite as\n> safe as \"only creating new files\", but it is relatively safe.\n\n>From (libc.info):\n\n -- Macro: int O_APPEND\n     The bit that enables append mode for the file.  If set, then all\n     `write' operations write the data at the end of the file, extending\n     it, regardless of the current file position.  This is the only\n     reliable way to append to a file.  In append mode, you are\n     guaranteed that the data you write will always go to the current\n     end of the file, regardless of other processes writing to the\n     file.  Conversely, if you simply set the file position to the end\n     of file and write, then another process can extend the file after\n     you set the file position but before you write, resulting in your\n     data appearing someplace before the real end of file.\n\nI don't quote understand how that would help hg (Mercurial) to have\noperations like commit, pull/fetch or push atomic, i.e. all or nothing.\nIn hg you have to update individual files (blobs buckets) storing delta\nand perhaps full version, update manifest file (flat tree) and update\nchangelog (commit): what happens if for example there are two concurrent\noperations trying to update repository, e.g. two push operations in parallel\n(from two different developers), or fetch from cron and commit? What\nhappens if operation is interrupted (e.g. lost connection to network during\nfetch)?\n\nIn git both situations result in some prune-able and fsck-visible crud in\nrepository, but repository stays uncorrupted, and all operations are atomic\n(all or nothing).\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"33136","messageId":"Pine.LNX.4.64.0701310959220.3021@xanadu.home","threadId":"6583","inReplyTo":"3c6c07c20701301938u4d1503a2m3e0af51121b8e6db@mail.gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-31T15:03:27Z","receivedAt":"2007-01-31T15:03:27Z","isPatch":false,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Tue, 30 Jan 2007, Mike Coleman wrote:\n\n> As for performance, my thinking was that since hg is implemented\n> apparently almost entirely in Python, and has (again apparently)\n> generally acceptable performance, this suggested that much of the\n> problem might be I/O-bound enough that language efficiency might not\n> matter so much.\n\nMatt Mackall said himself that some core portion of hg have been \nrewritten in C in order to improve performances.\n\n\nNicolas\n"},{"id":"33150","messageId":"Pine.LNX.4.64.0701310805500.3632@woody.linux-foundation.org","threadId":"6583","inReplyTo":"7vodofx06s.fsf@assigned-by-dhcp.cox.net","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-01-31T16:22:35Z","receivedAt":"2007-01-31T16:22:35Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 30 Jan 2007, Junio C Hamano wrote:\n\n> Linus Torvalds <torvalds@linux-foundation.org> writes:\n> > \n> > But I'll admit - my main reason going with C is (a) it's what I know and \n> > (b) I absolutely _hate_ being constrained by the language. The great thing \n> > about C (still) is that you can do *anything* in it. You're literally \n> > limited by hardware, and by your own abilities. Nothing else.\n> \n> Well, if you count \"time\" as part of your own ability then that\n> is true.  Some things are too cumbersome and not performance\n> critical enough to do in C.\n\nSure. I'd probably not do some graphical front-end in C - although some of \nthe toolkits make that resonable too. \n\nBut even for \"time\", C actually does have a number of big advantages that \nsome people often seem to overlook:\n\n - it has absolutely tons of infrastructure. Something like Perl comes \n   *close*, but in the end, even the Perl CPAN stuff is just a drop in the \n   bucket for what somebody programming in C has. Other scripting \n   languages? Outside of their specific things (ie the tcl/tk kind of \n   thing), they really have nothing.\n\n - perhaps even more importantly: there's a ton of clueful people who know \n   it. Maybe this stems from my personal blinders on what \"competent\" is \n   (and from just my sheltered life in general), but absolutely everybody \n   who is deeply competent will know C. Not everybody will want to program \n   in it, but they *all* know enough to be able to work with it.\n\nThe latter one is rather relevant for open source programming. Finding \nsome really competent person who has written a library to do (say, purely \nhypothetically - NOT!) a clean and efficient \"diff\" implementation can be \na huge deal. And you will find that using C. \n\nSo yeah, C is low-level. Yeah, you have to know how \"pointers\" work. And \nyeah, it takes effort especially to get started. But once you have gotten \nstarted, you realize that:\n\n - it may have been a lot more work to get over the hump, but once you \n   did, you can find people who can work with you and help you.\n\n - yeah, you didn't really want to work with people who didn't know how a \n   \"pointer to a function returning a const pointer\" really works.\n\nI agree that C is a really hard language for \"prototyping\". And yes, I'll \nalso agree that probably 95% of all programming is really about \nprototyping. Make something that works, and move on. In that environment, \nC is simply wrong.\n\nBut in a real core infrastructure environment, I'd say that almost \nanything *but* C (or \"fairly similar\" language) tends to be a mistake.\n\nSo I personally tend to always work on that infrastructure thing, which is \nwhy I love C. If it's not \"core enough\" that C is the proper language, I'm \nprobably simply not interested.\n\nAnd yeah, it will change. I realize that. My bet is that C will remain as \nthe default \"system language\" for at least another decade. \n\nOf course, is an SCM \"core enough\"? Some parts definitely are. The actual \nlow-level diff generation fairly obviously is. Is revision walking? \nPer-file operations? hg and git disagree about that decision.\n\n\t\tLinus\n"},{"id":"33156","messageId":"Pine.LNX.4.63.0701311733120.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0701310805500.3632@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-01-31T16:41:49Z","receivedAt":"2007-01-31T16:41:49Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 31 Jan 2007, Linus Torvalds wrote:\n\n> So yeah, C is low-level. Yeah, you have to know how \"pointers\" work. And \n> yeah, it takes effort especially to get started. But once you have \n> gotten started, you realize that:\n> \n>  - it may have been a lot more work to get over the hump, but once you \n>    did, you can find people who can work with you and help you.\n> \n>  - yeah, you didn't really want to work with people who didn't know how a \n>    \"pointer to a function returning a const pointer\" really works.\n\nProbably related to the second point:\n\n- you do _not_ want to work with people who a scared of pointers. Most \n  such people are only scared of it, because they are not _able_ to clean \n  up after themselves. This leads _invariably_ to bad code.\n\nFor example, I have never ever seen so bad code as in Java. If you are not \nforced by the language to clean up the data structures, you tend to get \nlazy. You don't free memory (why should I? It's garbage collected anyway, \nright?), you don't close resources, you _waste_ time by using incorrect \ndata-types or doing wholesale copying all the time.\n\nJust look at Eclipse's source code. *tries not to vomit on the keyboard*\n\nAll this is a real pity, because when you see Java code by a guy who \nlearnt the ropes in C, and learnt Java properly, it is just elegant and \nconcise. And it gives a huge development boost, because you have so much \ninfrastructure already.\n\n> I agree that C is a really hard language for \"prototyping\".\n\nThat depends. I cannot do it, I am too stupid. But I saw a guy prototyping \nin assembler, using his assembler library. That was _fast_!\n\nOh well, I try to stop rambling for today, and do something productive \nagain.\n\nCiao,\nDscho\n"},{"id":"33158","messageId":"3c6c07c20701310858v488ebbd4k98cd14340661f086@mail.gmail.com","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0701310959220.3021@xanadu.home","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Mike Coleman","fromEmail":"tutufan@gmail.com","sentAt":"2007-01-31T16:58:28Z","receivedAt":"2007-01-31T16:58:28Z","isPatch":false,"sender":{"key":"tutufan@gmail.com","avatar":null},"body":"On 1/31/07, Nicolas Pitre <nico@cam.org> wrote:\n> Matt Mackall said himself that some core portion of hg have been\n> rewritten in C in order to improve performances.\n\nFor what it's worth, sloccount reports the following:\n\ngit: 52K C, 17K Perl, 10K sh, 6K Tcl, 300 Python\n\nhg: 14K Python, 700 C\n\nSpeculating wildly, I'd be surprised if the C part of git couldn't be\nreduced below 5K, at a cost of an 8K increase in Perl (or Python), and\nnot more than a doubling of runtime.  (This speculation is for\nentertainment purposes only--I'm not suggesting a course of action.)\n\nMike\n"},{"id":"33170","messageId":"7vabzzvud0.fsf@assigned-by-dhcp.cox.net","threadId":"6583","inReplyTo":"eppshi$1l4$1@sea.gmane.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-31T20:01:15Z","receivedAt":"2007-01-31T20:01:15Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Theodore Tso wrote:\n>> \n>> To be fair hg modifies files using O_APPEND only.  That isn't quite as\n>> safe as \"only creating new files\", but it is relatively safe.\n>\n> From (libc.info):\n>  -- Macro: int O_APPEND\n>  ...\n> I don't quote understand how that would help hg (Mercurial) to have\n> operations like commit, pull/fetch or push atomic, i.e. all or nothing.\n\nIf I remember correctly, thanks to their log-like file format,\nthey can rely on O_APPEND to do the right thing when growing,\nand aborting the current transaction is just a truncate away (or\na set of truncates on the files appended in the transaction, if\nhg touches more than one log-like file but I do not know if hg\nuses only one file or more than one).  That's one of the things\nI found clean and beautiful (from theoretical point of view, at\nleast) in their design.  I do not think O_APPEND is not used to\ncontrol concurrent operations.\n"},{"id":"33181","messageId":"20070131222507.GO10108@waste.org","threadId":"6583","inReplyTo":"eppshi$1l4$1@sea.gmane.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Matt Mackall","fromEmail":"mpm@selenic.com","sentAt":"2007-01-31T22:25:07Z","receivedAt":"2007-01-31T22:25:07Z","isPatch":false,"sender":{"key":"mpm@selenic.com","avatar":null},"body":"On Wed, Jan 31, 2007 at 11:56:01AM +0100, Jakub Narebski wrote:\n> Theodore Tso wrote:\n> \n> > On Tue, Jan 30, 2007 at 11:55:48AM -0500, Shawn O. Pearce wrote:\n> >> I think hg modifies files as it goes, which could cause some issues\n> >> when a writer is aborted.  I'm sure they have thought about the\n> >> problem and tried to make it safe, but there isn't anything safer\n> >> than just leaving the damn thing alone.  :)\n> > \n> > To be fair hg modifies files using O_APPEND only.  That isn't quite as\n> > safe as \"only creating new files\", but it is relatively safe.\n> \n> >From (libc.info):\n> \n>  -- Macro: int O_APPEND\n>      The bit that enables append mode for the file.  If set, then all\n>      `write' operations write the data at the end of the file, extending\n>      it, regardless of the current file position.  This is the only\n>      reliable way to append to a file.  In append mode, you are\n>      guaranteed that the data you write will always go to the current\n>      end of the file, regardless of other processes writing to the\n>      file.  Conversely, if you simply set the file position to the end\n>      of file and write, then another process can extend the file after\n>      you set the file position but before you write, resulting in your\n>      data appearing someplace before the real end of file.\n> \n> I don't quote understand how that would help hg (Mercurial) to have\n> operations like commit, pull/fetch or push atomic, i.e. all or nothing.\n\nThat's because it's unrelated.\n\n> In hg you have to update individual files (blobs buckets) storing delta\n> and perhaps full version, update manifest file (flat tree) and update\n> changelog (commit): what happens if for example there are two concurrent\n> operations trying to update repository, e.g. two push operations in parallel\n> (from two different developers), or fetch from cron and commit?\n\nMercurial has write-side locks so there can only ever be one writer at\na time. There are no locks needed on the read side, so there can be\nany number of readers, even while commits are happening.\n\n> What happens if operation is interrupted (e.g. lost connection to\n> network during fetch)?\n\nWe keep a simple transaction journal. As Mercurial revlogs are\nappend-only, rolling back a transaction just means truncating all\nfiles in a transaction to their original length.\n\n> In git both situations result in some prune-able and fsck-visible crud in\n> repository, but repository stays uncorrupted, and all operations are atomic\n> (all or nothing).\n\nIf a Mercurial transaction is interrupted and not rolled back, the\nresult is prune-able and fsck-visible crud. But this doesn't happen\nmuch in practice.\n\nThe claim that's been made is that a) truncate is unsafe because Linux\nhas historically had problems in this area and b) git is safer because\nit doesn't do this sort of thing. \n\nMy response is a) those problems are overstated and Linux has never\nhad difficulty with the sorts of straightforward single writer\noperations Mercurial uses and b) normal git usage involves regular\nrewrites of data with packing operations that makes its exposure to\nfilesystem bugs equivalent or greater.\n\nIn either case, both provide strong integrity checks with recursive\nSHA1 hashing, zlib CRCs, and GPG signatures (as well as distributed\n\"back-up\"!) so this is largely a non-issue relative to traditional\nsystems.\n\n-- \nMathematics is the supreme nostalgia of our time.\n"},{"id":"33192","messageId":"200702010058.43431.jnareb@gmail.com","threadId":"6583","inReplyTo":"20070131222507.GO10108@waste.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-01-31T23:58:42Z","receivedAt":"2007-01-31T23:58:42Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Matt Mackall wrote:\n> On Wed, Jan 31, 2007 at 11:56:01AM +0100, Jakub Narebski wrote:\n>> Theodore Tso wrote:\n>> \n>>> On Tue, Jan 30, 2007 at 11:55:48AM -0500, Shawn O. Pearce wrote:\n>>>> I think hg modifies files as it goes, which could cause some issues\n>>>> when a writer is aborted.  I'm sure they have thought about the\n>>>> problem and tried to make it safe, but there isn't anything safer\n>>>> than just leaving the damn thing alone.  :)\n>>> \n>>> To be fair hg modifies files using O_APPEND only.  That isn't quite\n>>> as safe as \"only creating new files\", but it is relatively safe.\n>> \n>>>From (libc.info):\n>> \n>>  -- Macro: int O_APPEND\n[...] \n>> I don't quote understand how that would help hg (Mercurial) to have\n>> operations like commit, pull/fetch or push atomic, i.e. all or\n>> nothing. \n> \n> That's because it's unrelated.\n[...]\n> Mercurial has write-side locks so there can only ever be one writer at\n> a time. There are no locks needed on the read side, so there can be\n> any number of readers, even while commits are happening.\n> \n>> What happens if operation is interrupted (e.g. lost connection to\n>> network during fetch)?\n> \n> We keep a simple transaction journal. As Mercurial revlogs are\n> append-only, rolling back a transaction just means truncating all\n> files in a transaction to their original length.\n\nThanks a lot for complete answer. So Mercurial uses write-side locks\nfor dealing with concurrent operations, and transaction journal for\ndealing with interrupted operations. I guess that incomplete transactions\nare rolled back on next hg command...\n\nI guess (please correct me if I'm wrong) that git uses \"put reference\nafter putting data\" scheme, and write-side lock in few places when it\nis needed.\n \n>> In git both situations result in some prune-able and fsck-visible crud in\n>> repository, but repository stays uncorrupted, and all operations are atomic\n>> (all or nothing).\n> \n> If a Mercurial transaction is interrupted and not rolled back, the\n> result is prune-able and fsck-visible crud. But this doesn't happen\n> much in practice.\n> \n> The claim that's been made is that a) truncate is unsafe because Linux\n> has historically had problems in this area and b) git is safer because\n> it doesn't do this sort of thing. \n> \n> My response is a) those problems are overstated and Linux has never\n> had difficulty with the sorts of straightforward single writer\n> operations Mercurial uses and b) normal git usage involves regular\n> rewrites of data with packing operations that makes its exposure to\n> filesystem bugs equivalent or greater.\n\nRewrites in git perhaps are (or should be) regular, but need not be often.\nAnd with new idea/feature of kept packs rewrite need not be of full data.\n\nOne command which _is_ (a bit) unsafe in git is git-prune. I'm not sure\nif it could be made safe. But not doing prune affects only a bit\nrepository size (where git is best I think of all SCMs) and not performance.\n\nOn the other hand hg repository structure (namely log like append changelog\n/ revlog to store commits) makes it I think hard to have multiple persistent\nbranches.\n\nSidenote 1: it looks like git is optimized for speed of merge and checkout\n(branch switching, or going to given point in history for bisect), and\nprobably accidentally for multi-branch repos, while Mercurial is optimized\nfor speed of commit and patch.\n\nSidenote 2: Mercurial repository structure might make it use \"file-ids\"\n(perhaps implicitely), with all the disadvantages (different renames\non different branches) of those.\n\n> In either case, both provide strong integrity checks with recursive\n> SHA1 hashing, zlib CRCs, and GPG signatures (as well as distributed\n> \"back-up\"!) so this is largely a non-issue relative to traditional\n> systems.\n\nIntegrity checks can tell you that repository is corrupted, but it would\nbe better if it didn't get corrupted in first place.\n\nBesides: zlib CRC for Mercurial? I thought that hg didn't compress the\ndata, only delta chain store it?\n-- \nJakub Narebski\nPoland\n"},{"id":"33197","messageId":"20070201003429.GQ10108@waste.org","threadId":"6583","inReplyTo":"200702010058.43431.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Matt Mackall","fromEmail":"mpm@selenic.com","sentAt":"2007-02-01T00:34:29Z","receivedAt":"2007-02-01T00:34:29Z","isPatch":false,"sender":{"key":"mpm@selenic.com","avatar":null},"body":"On Thu, Feb 01, 2007 at 12:58:42AM +0100, Jakub Narebski wrote:\n> Matt Mackall wrote:\n> > On Wed, Jan 31, 2007 at 11:56:01AM +0100, Jakub Narebski wrote:\n> >> Theodore Tso wrote:\n> >> \n> >>> On Tue, Jan 30, 2007 at 11:55:48AM -0500, Shawn O. Pearce wrote:\n> >>>> I think hg modifies files as it goes, which could cause some issues\n> >>>> when a writer is aborted.  I'm sure they have thought about the\n> >>>> problem and tried to make it safe, but there isn't anything safer\n> >>>> than just leaving the damn thing alone.  :)\n> >>> \n> >>> To be fair hg modifies files using O_APPEND only.  That isn't quite\n> >>> as safe as \"only creating new files\", but it is relatively safe.\n> >> \n> >>>From (libc.info):\n> >> \n> >>  -- Macro: int O_APPEND\n> [...] \n> >> I don't quote understand how that would help hg (Mercurial) to have\n> >> operations like commit, pull/fetch or push atomic, i.e. all or\n> >> nothing. \n> > \n> > That's because it's unrelated.\n> [...]\n> > Mercurial has write-side locks so there can only ever be one writer at\n> > a time. There are no locks needed on the read side, so there can be\n> > any number of readers, even while commits are happening.\n> > \n> >> What happens if operation is interrupted (e.g. lost connection to\n> >> network during fetch)?\n> > \n> > We keep a simple transaction journal. As Mercurial revlogs are\n> > append-only, rolling back a transaction just means truncating all\n> > files in a transaction to their original length.\n> \n> Thanks a lot for complete answer. So Mercurial uses write-side locks\n> for dealing with concurrent operations, and transaction journal for\n> dealing with interrupted operations. I guess that incomplete transactions\n> are rolled back on next hg command...\n\nThey are either automatically rolled back on abort or if that fails\nfor some reason like power failure the user is prompted to run \"hg\nrecover\" to complete the rollback. We also save the last transaction\njournal which allows one level of undo for pulls/commits.\n\n> I guess (please correct me if I'm wrong) that git uses \"put reference\n> after putting data\" scheme, and write-side lock in few places when it\n> is needed.\n\nMercurial also uses a \"put reference after putting data\" which is what\nallows us to have no read vs write locking.\n  \n> >> In git both situations result in some prune-able and fsck-visible crud in\n> >> repository, but repository stays uncorrupted, and all operations are atomic\n> >> (all or nothing).\n> > \n> > If a Mercurial transaction is interrupted and not rolled back, the\n> > result is prune-able and fsck-visible crud. But this doesn't happen\n> > much in practice.\n> > \n> > The claim that's been made is that a) truncate is unsafe because Linux\n> > has historically had problems in this area and b) git is safer because\n> > it doesn't do this sort of thing. \n> > \n> > My response is a) those problems are overstated and Linux has never\n> > had difficulty with the sorts of straightforward single writer\n> > operations Mercurial uses and b) normal git usage involves regular\n> > rewrites of data with packing operations that makes its exposure to\n> > filesystem bugs equivalent or greater.\n> \n> Rewrites in git perhaps are (or should be) regular, but need not be often.\n> And with new idea/feature of kept packs rewrite need not be of full data.\n\nIf the set of files in a given commit (say tip) gets spread out across\nan arbitrary number of packs ordered by last modification time,\nperformance degrades to O(n) lookups and random seeking.\n\n> One command which _is_ (a bit) unsafe in git is git-prune. I'm not sure\n> if it could be made safe. But not doing prune affects only a bit\n> repository size (where git is best I think of all SCMs) and not performance.\n> \n> On the other hand hg repository structure (namely log like append changelog\n> / revlog to store commits) makes it I think hard to have multiple persistent\n> branches.\n\nNot sure why you think that. There are some difficulties here, but\nthey're mostly owing to the fact that we've always emphasized the one\nbranch per repo approach as being the most user-friendly.\n\n> Sidenote 1: it looks like git is optimized for speed of merge and checkout\n> (branch switching, or going to given point in history for bisect), and\n> probably accidentally for multi-branch repos, while Mercurial is optimized\n> for speed of commit and patch.\n\nI think all of these things are comparable.\n\n> Sidenote 2: Mercurial repository structure might make it use \"file-ids\"\n> (perhaps implicitely), with all the disadvantages (different renames\n> on different branches) of those.\n\nNope.\n\n> > In either case, both provide strong integrity checks with recursive\n> > SHA1 hashing, zlib CRCs, and GPG signatures (as well as distributed\n> > \"back-up\"!) so this is largely a non-issue relative to traditional\n> > systems.\n> \n> Integrity checks can tell you that repository is corrupted, but it would\n> be better if it didn't get corrupted in first place.\n\nObviously. Hence our append-only design. Data that's written to a repo\nis never rewritten, which minimizes exposure to software bugs and I/O\nerrors.\n \n> Besides: zlib CRC for Mercurial? I thought that hg didn't compress the\n> data, only delta chain store it?\n\nWe use zlib compression of deltas and have since April 6, 2005.\n\n-- \nMathematics is the supreme nostalgia of our time.\n"},{"id":"33198","messageId":"200702010157.51452.jnareb@gmail.com","threadId":"6583","inReplyTo":"20070201003429.GQ10108@waste.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-01T00:57:51Z","receivedAt":"2007-02-01T00:57:51Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Matt Mackall wrote:\n> On Thu, Feb 01, 2007 at 12:58:42AM +0100, Jakub Narebski wrote:\n\n>> Sidenote 1: it looks like git is optimized for speed of merge and checkout\n>> (branch switching, or going to given point in history for bisect), and\n>> probably accidentally for multi-branch repos, while Mercurial is optimized\n>> for speed of commit and patch.\n> \n> I think all of these things are comparable.\n\nHierarchical tree objects in git optimize for speed of merge and checkout\nIMVHO, as you need only to check out one hash to know if you have to\ndescend into subdirectory, or if given subdirectory haven't changed.\nFlat manifest file in Mercurial (and also \"filename buckets\") makes\ncommits faster, I think.\n\n>> Sidenote 2: Mercurial repository structure might make it use \"file-ids\"\n>> (perhaps implicitely), with all the disadvantages (different renames\n>> on different branches) of those.\n> \n> Nope.\n\nHow it is so, if the blobs (file contents) are stored filename hashed?\nIIRC hg has some scheme to deal with renames, but it is file-id (file\nidentity) based AFAIK.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"33211","messageId":"45C19DD0.20504@fs.ei.tum.de","threadId":"6583","inReplyTo":"200702010157.51452.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Simon 'corecode' Schubert","fromEmail":"corecode@fs.ei.tum.de","sentAt":"2007-02-01T07:59:12Z","receivedAt":"2007-02-01T07:59:12Z","isPatch":false,"sender":{"key":"corecode@fs.ei.tum.de","avatar":"https://gravatar.com/avatar/eff9dbf0cdac0d1e6a6cd7ed0e50763edcb376b493b5253a35ff167918ad79e1?d=mp&s=160"},"body":"Jakub Narebski wrote:\n>>> Sidenote 2: Mercurial repository structure might make it use \"file-ids\"\n>>> (perhaps implicitely), with all the disadvantages (different renames\n>>> on different branches) of those.\n>> Nope.\n> How it is so, if the blobs (file contents) are stored filename hashed?\n> IIRC hg has some scheme to deal with renames, but it is file-id (file\n> identity) based AFAIK.\n\nNo, the buckets are simply the filename.  If you rename, you take the penalty of duplicating the content (compressed) with a new name.  No big deal there.  So there are *no* file-ids.  Blobs go into the data/index file which corresponds to their filename.\n\ncheers\n  simon\n\n-- \nServe - BSD     +++  RENT this banner advert  +++    ASCII Ribbon   /\"\\\nWork - Mac      +++  space for low €€€ NOW!1  +++      Campaign     \\ /\nParty Enjoy Relax   |   http://dragonflybsd.org      Against  HTML   \\\nDude 2c 2 the max   !   http://golden-apple.biz       Mail + News   / \\\n\n"},{"id":"33220","messageId":"Pine.LNX.4.63.0702011108430.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"6583","inReplyTo":"45C19DD0.20504@fs.ei.tum.de","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-02-01T10:09:45Z","receivedAt":"2007-02-01T10:09:45Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\n[culled many people from the Cc: list to avoid a flamewar]\n\nOn Thu, 1 Feb 2007, Simon 'corecode' Schubert wrote:\n\n> If you rename, you take the penalty of duplicating the content \n> (compressed) with a new name.  No big deal there. So there are *no* \n> file-ids.  Blobs go into the data/index file which corresponds to their \n> filename.\n\nSo, can you explain to me how a filename is _not_ a file-id?\n\nCiao,\nDscho\n"},{"id":"33221","messageId":"45C1BDD3.8050103@fs.ei.tum.de","threadId":"6583","inReplyTo":"Pine.LNX.4.63.0702011108430.22628@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Simon 'corecode' Schubert","fromEmail":"corecode@fs.ei.tum.de","sentAt":"2007-02-01T10:15:47Z","receivedAt":"2007-02-01T10:15:47Z","isPatch":false,"sender":{"key":"corecode@fs.ei.tum.de","avatar":"https://gravatar.com/avatar/eff9dbf0cdac0d1e6a6cd7ed0e50763edcb376b493b5253a35ff167918ad79e1?d=mp&s=160"},"body":"Johannes Schindelin wrote:\n>> If you rename, you take the penalty of duplicating the content \n>> (compressed) with a new name.  No big deal there. So there are *no* \n>> file-ids.  Blobs go into the data/index file which corresponds to their \n>> filename.\n> So, can you explain to me how a filename is _not_ a file-id?\n\nIt is not a file-id like other SCM use it (I think monotone, not sure though).  If you copy/move the content to a new name, the ID will not stay the same.  Just see it as a hash bucket which allows you easy access to the history for a file currently with this name.\n\ncheers\n  simon\n\n-- \nServe - BSD     +++  RENT this banner advert  +++    ASCII Ribbon   /\"\\\nWork - Mac      +++  space for low €€€ NOW!1  +++      Campaign     \\ /\nParty Enjoy Relax   |   http://dragonflybsd.org      Against  HTML   \\\nDude 2c 2 the max   !   http://golden-apple.biz       Mail + News   / \\\n\n"},{"id":"33224","messageId":"Pine.LNX.4.63.0702011149290.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"6583","inReplyTo":"45C1BDD3.8050103@fs.ei.tum.de","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-02-01T10:49:52Z","receivedAt":"2007-02-01T10:49:52Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 1 Feb 2007, Simon 'corecode' Schubert wrote:\n\n> Johannes Schindelin wrote:\n> > > If you rename, you take the penalty of duplicating the content\n> > > (compressed) with a new name.  No big deal there. So there are *no*\n> > > file-ids.  Blobs go into the data/index file which corresponds to their\n> > > filename.\n> > So, can you explain to me how a filename is _not_ a file-id?\n> \n> It is not a file-id like other SCM use it (I think monotone, not sure though).\n> If you copy/move the content to a new name, the ID will not stay the same.\n> Just see it as a hash bucket which allows you easy access to the history for a\n> file currently with this name.\n\nAh, thanks. I misunderstood the meaning of file-id in _that_ context.\n\nCiao,\nDscho\n"},{"id":"33250","messageId":"Pine.LNX.4.64.0702010814470.3632@woody.linux-foundation.org","threadId":"6583","inReplyTo":"45C1BDD3.8050103@fs.ei.tum.de","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-01T16:28:04Z","receivedAt":"2007-02-01T16:28:04Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Thu, 1 Feb 2007, Simon 'corecode' Schubert wrote:\n>\n> > So, can you explain to me how a filename is _not_ a file-id?\n> \n> It is not a file-id like other SCM use it (I think monotone, not sure though).\n> If you copy/move the content to a new name, the ID will not stay the same.\n> Just see it as a hash bucket which allows you easy access to the history for a\n> file currently with this name.\n\nWell, that's actually just another \"file ID\" too. It's just not an \"inode \nnumber\" kind of file ID, it's more the \"CVS file ID\" kind of ID.\n\nSVN uses \"inode numbers\" (I think they are just UUID's generated at \"svn \nadd\" time, but I'm not sure) to track file ID's across renames. Some other \nSCM's do the same.\n\nCVS uses \"pathname\" as the file ID (which obviously doesn't need any \nseparate generation at all), which is why you have to do horrible things \nto track file ID's across renames (ie you really can't, but you *can* copy \nor move the *,v file so that your *new* \"file ID\" also has the same \nhistory as your old one).\n\nSo both of those are \"file ID's\" - they are what is used to index into the \nhistory, and they have real meaning for very fundamental operations.\n\nYou can view git as \"closer\" to CVS, in the sense that it certainly \ndoesn't have the SVN kind of location-independent ID, and it _is_ able to \nlook back in history using the path-name. So in that sense, you can \ncertainly claim that the pathname is the \"file ID\" in git too, and that \ngit is closer to CVS than to SVN.\n\nBut unlike SVN or CVS, there is no real fundamental \"meaning\" to the \npathname in git. Sure, you can use the pathname to trace history of a \nfile, but on the other hand, you can use a random aggregation of pathnames \nto track history of a set of files and directories, and the pathnames \nactually exist even when the file doesn't. So there obviously isn't any \n1:1 relationship, neither in usage, nor in any internal implementation.\n\nSo at least for me, \"file ID\" means \"identifier for a particular chain of \nhistory\". THAT exists in both CVS and SVN (it's a pathname and an \"inode \nnumber\" respectively), but does not exist in git at all.\n\n\t\t\tLinus\n"},{"id":"33274","messageId":"20070201193647.GA18234@soma","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0702010814470.3632@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2007-02-01T19:36:47Z","receivedAt":"2007-02-01T19:36:47Z","isPatch":false,"sender":{"key":"e@80x24.org","avatar":null},"body":"Linus Torvalds <torvalds@linux-foundation.org> wrote:\n> On Thu, 1 Feb 2007, Simon 'corecode' Schubert wrote:\n> >\n> > > So, can you explain to me how a filename is _not_ a file-id?\n> > \n> > It is not a file-id like other SCM use it (I think monotone, not sure though).\n> > If you copy/move the content to a new name, the ID will not stay the same.\n> > Just see it as a hash bucket which allows you easy access to the history for a\n> > file currently with this name.\n> \n> Well, that's actually just another \"file ID\" too. It's just not an \"inode \n> number\" kind of file ID, it's more the \"CVS file ID\" kind of ID.\n> \n> SVN uses \"inode numbers\" (I think they are just UUID's generated at \"svn \n> add\" time, but I'm not sure) to track file ID's across renames. Some other \n> SCM's do the same.\n\nI think you got this part confused with GNU Arch (and possibly\nBzr).  SVN tracks renames in the changeset, it records (in the log)\na copy and delete.  pathname@revision is the only \"file ID\" I know\nabout in SVN.\n\n-- \nEric Wong\n"},{"id":"33287","messageId":"Pine.LNX.4.64.0702011313150.5982@woody.linux-foundation.org","threadId":"6583","inReplyTo":"20070201193647.GA18234@soma","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-01T21:13:55Z","receivedAt":"2007-02-01T21:13:55Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Thu, 1 Feb 2007, Eric Wong wrote:\n> > SVN uses \"inode numbers\" (I think they are just UUID's generated at \"svn \n> > add\" time, but I'm not sure) to track file ID's across renames. Some other \n> > SCM's do the same.\n> \n> I think you got this part confused with GNU Arch (and possibly\n> Bzr).  SVN tracks renames in the changeset, it records (in the log)\n> a copy and delete.  pathname@revision is the only \"file ID\" I know\n> about in SVN.\n\nAhh, I was sure the revision files in FSFS were per-file, but coor me \ncorrected - they seem to be per-revision.\n\nMy bad.\n\n\t\tLinus\n"},{"id":"33364","messageId":"200702021055.49428.jnareb@gmail.com","threadId":"6583","inReplyTo":"20070201003429.GQ10108@waste.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-02T09:55:48Z","receivedAt":"2007-02-02T09:55:48Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Thu, 01 Feb 2007 00:00:00 +0100, Matt Mackall wrote:\n> On Thu, Feb 01, 2007 at 12:58:42AM +0100, Jakub Narebski wrote:\n>> Matt Mackall wrote:\n\n>> On the other hand hg repository structure (namely log like append changelog\n>> / revlog to store commits) makes it I think hard to have multiple persistent\n>> branches.\n> \n> Not sure why you think that. There are some difficulties here, but\n> they're mostly owing to the fact that we've always emphasized the one\n> branch per repo approach as being the most user-friendly.\n\nWell, perhaps I should say that append-log changelog / revlog[*1*] structure\nto store commits makes it natural to have one branch per repository, as\nbranch (in the lineage of given commit meaning, i.e. all commits which\nare ancestors of given commit) is roughly equivalent to changelog / revlog\nand branch tip (latest commit on a branch) is top commit (latest entry)\nin changelog / revlog.\n\nIn git, with its DAG (direct acyclic graph) of commits and branch tip as\na moving pointer (top of stack pointer like moving) to a commit in DAG\nmakes it natural to have multiple branches in a repository (current branch\nis branch pointed by HEAD, another pointer - to branch this time[*2*]).\n\nPerhaps multiple branch repository makes learning curve a bit steeper,\nbut also encourages using temporary branches and topic branches, which\nmakes _development_ (as opposed to using version control tool) more\n(power)user-friendly; and makes SCM more powerfull.\n\n\nHow Mercurial solves problem of multiple _persistent_ branches? Does it\nadd pointers to commits somewhere deeper in changelog / revlog?\n\nBTW does Mercurial have tags?\n\n>>> In either case, both provide strong integrity checks with recursive\n>>> SHA1 hashing, zlib CRCs, and GPG signatures (as well as distributed\n>>> \"back-up\"!) so this is largely a non-issue relative to traditional\n>>> systems.\n>> \n>> Integrity checks can tell you that repository is corrupted, but it would\n>> be better if it didn't get corrupted in first place.\n> \n> Obviously. Hence our append-only design. Data that's written to a repo\n> is never rewritten, which minimizes exposure to software bugs and I/O\n> errors.\n\nBy the way, RCS / CVS rewrote relevant data (to have diff from the top\nstructure) on each commit.\n\nI wonder if git could generate pack on the fly fastimport like...\n\n>> Besides: zlib CRC for Mercurial? I thought that hg didn't compress the\n>> data, only delta chain store it?\n> \n> We use zlib compression of deltas and have since April 6, 2005.\n\nNice to know. You compress only file deltas, or also file revision\nmetadata? Do you compress manifests (trees) and commits (or at least\ncommit messages) too?\n\nFootnotes:\n----------\n\n[*1*] I don't know what nomenclature Mercurial uses for blobs (file\ncontents), trees (directory contents) and commits (revision contents)\nstorage.\n\n[*2*] I disregard here latest work on \"detached HEAD\" in git.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"33380","messageId":"45C341CD.7020301@fs.ei.tum.de","threadId":"6583","inReplyTo":"200702021055.49428.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Simon 'corecode' Schubert","fromEmail":"corecode@fs.ei.tum.de","sentAt":"2007-02-02T13:51:09Z","receivedAt":"2007-02-02T13:51:09Z","isPatch":false,"sender":{"key":"corecode@fs.ei.tum.de","avatar":"https://gravatar.com/avatar/eff9dbf0cdac0d1e6a6cd7ed0e50763edcb376b493b5253a35ff167918ad79e1?d=mp&s=160"},"body":"Jakub Narebski wrote:\n>>> Integrity checks can tell you that repository is corrupted, but it would\n>>> be better if it didn't get corrupted in first place.\n>> Obviously. Hence our append-only design. Data that's written to a repo\n>> is never rewritten, which minimizes exposure to software bugs and I/O\n>> errors.\n> \n> By the way, RCS / CVS rewrote relevant data (to have diff from the top\n> structure) on each commit.\n> \n> I wonder if git could generate pack on the fly fastimport like...\n\nWhat do you mean with that?  generate the pack on which occasion?  CVS import?  I do this already.\n\ncheers\n  simon\n\n-- \nServe - BSD     +++  RENT this banner advert  +++    ASCII Ribbon   /\"\\\nWork - Mac      +++  space for low €€€ NOW!1  +++      Campaign     \\ /\nParty Enjoy Relax   |   http://dragonflybsd.org      Against  HTML   \\\nDude 2c 2 the max   !   http://golden-apple.biz       Mail + News   / \\\n\n"},{"id":"33381","messageId":"200702021523.38169.jnareb@gmail.com","threadId":"6583","inReplyTo":"45C341CD.7020301@fs.ei.tum.de","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-02T14:23:37Z","receivedAt":"2007-02-02T14:23:37Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Simon 'corecode' Schubert wrote:\n> Jakub Narebski wrote:\n>> \n>> By the way, RCS / CVS rewrote relevant data (to have diff from the top\n>> structure) on each commit.\n>> \n>> I wonder if git could generate pack on the fly fastimport like...\n> \n> What do you mean with that?  generate the pack on which occasion?\n> CVS import?  I do this already. \n\nOn commit.\n-- \nJakub Narebski\nPoland\n"},{"id":"33384","messageId":"20070202150212.GA14691@spearce.org","threadId":"6583","inReplyTo":"200702021523.38169.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-02-02T15:02:12Z","receivedAt":"2007-02-02T15:02:12Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> wrote:\n> Simon 'corecode' Schubert wrote:\n> > Jakub Narebski wrote:\n> >> \n> >> By the way, RCS / CVS rewrote relevant data (to have diff from the top\n> >> structure) on each commit.\n> >> \n> >> I wonder if git could generate pack on the fly fastimport like...\n> > \n> > What do you mean with that?  generate the pack on which occasion?\n> > CVS import?  I do this already. \n> \n> On commit.\n\nI've thought about doing this.  Except there are three independent\nprocesses occuring during commit that generate objects:\n\n\tupdate-index\n\twrite-tree\n\tcommit-tree\n\nand the update-index portion is also git-add, which we have now\nstarted to encourage users to do ahead of time as often as needed,\nprior to running git-commit.  Its also the one that generates the\nlargest set of new objects for most projects.\n\nOne problem comes that we have a rule: \"don't delta an object\nwhich is already in a pack, unless -f is given\".  This is one of\nthe reasons `git repack -a -d -l` is so dang fast.  Its assuming\nall new stuff is loose, and therefore should be delta'd, but the\nold stuff which we have already delta'd is kept as-is.\n\n\nBasically I've thought about doing this (after my work in gfi)\nand decided its not worth the level of effort involved at this time.\nSo I'm not going to do it.  Someone else can try.  ;-)\n\n-- \nShawn.\n"},{"id":"33387","messageId":"slrnes6mmr.3l6.mdw@metalzone.distorted.org.uk","threadId":"6583","inReplyTo":"200702021055.49428.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Mark Wooding","fromEmail":"mdw@distorted.org.uk","sentAt":"2007-02-02T15:38:03Z","receivedAt":"2007-02-02T15:38:03Z","isPatch":false,"sender":{"key":"mdw@distorted.org.uk","avatar":null},"body":"Jakub Narebski <jnareb@gmail.com> wrote:\n\n> BTW does Mercurial have tags?\n\nYes.  Mercurial stores tags in text files, one per line, mapping the tag\nname to a SHA1 hash of the tagged revision.  There are two files of\ntags: `local' tags go into .hg/tags (or somesuch) and don't get copied\nby clone; global tags go into .hgtags and do get copied (of course,\nsince they're part of the source tree).\n\nIf I may be opinionated for a bit: this is barking for two reasons:\n\n  * The tags files grow by having lines added to the bottom.  Files of\n    this kind are almost ideal for causing merge conflicts, and there's\n    no automatic means for resolving them.  (I actually wrote a custom\n    tags merger recently -- if anyone wants it, just mail me.)\n\n  * If I visit a tag, and then decide I want to visit some other, more\n    recent tag, I'm screwed because it obviously didn't exist in that\n    old revision.  Tying tags to the revision history in this way is\n    truly daft.\n\n-- [mdw]\n"},{"id":"33392","messageId":"20070202160317.GX10108@waste.org","threadId":"6583","inReplyTo":"200702021055.49428.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Matt Mackall","fromEmail":"mpm@selenic.com","sentAt":"2007-02-02T16:03:17Z","receivedAt":"2007-02-02T16:03:17Z","isPatch":false,"sender":{"key":"mpm@selenic.com","avatar":null},"body":"On Fri, Feb 02, 2007 at 10:55:48AM +0100, Jakub Narebski wrote:\n> How Mercurial solves problem of multiple _persistent_ branches? Does it\n> add pointers to commits somewhere deeper in changelog / revlog?\n\nEach changeset may have a branch marker.\n\nHere's branches in use with an import of mutt's CVS history:\n\n$ hg branches\nmutt-0-94                      208:b2cc0abd8fe0\nHEAD                           207:a505693b54c1\nmutt-0-93                      134:d59345944030\nmuttintl                       1:29510de8b3fc\n$ hg co HEAD\n176 files updated, 0 files merged, 8 files removed, 0 files unresolved\n$ hg branch\nHEAD\n$ hg branch devel\n$ hg branch\ndevel\n$ hg branch devel\n\n> BTW does Mercurial have tags?\n\nYes. Both local and revision-controlled.\n\n> Nice to know. You compress only file deltas, or also file revision\n> metadata? Do you compress manifests (trees) and commits (or at least\n> commit messages) too?\n\nAll three use the same underlying storage format, so yes.\n\n-- \nMathematics is the supreme nostalgia of our time.\n"},{"id":"33389","messageId":"epvnln$fmn$1@sea.gmane.org","threadId":"6583","inReplyTo":"slrnes6mmr.3l6.mdw@metalzone.distorted.org.uk","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-02T16:09:47Z","receivedAt":"2007-02-02T16:09:47Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Mark Wooding wrote:\n\n> Jakub Narebski <jnareb@gmail.com> wrote:\n> \n>> BTW does Mercurial have tags?\n> \n> Yes.  Mercurial stores tags in text files, one per line, mapping the tag\n> name to a SHA1 hash of the tagged revision.  There are two files of\n> tags: `local' tags go into .hg/tags (or somesuch) and don't get copied\n> by clone; global tags go into .hgtags and do get copied (of course,\n> since they're part of the source tree).\n\nGaaah. Why anyone would want to have non-propagated tags?\n\nDo I understand correctly that Mercurial doesn't have annotated tags\n(this also means that it doesn't have PGP/GPG signed tags), and only\nequivalent of git lightweight tags?\n \n> If I may be opinionated for a bit: this is barking for two reasons:\n> \n>   * The tags files grow by having lines added to the bottom.  Files of\n>     this kind are almost ideal for causing merge conflicts, and there's\n>     no automatic means for resolving them.  (I actually wrote a custom\n>     tags merger recently -- if anyone wants it, just mail me.)\n\nSuch a merger (merge strategy) would be also useful for other log-like\nfiles, e.g. ChangeLogs and such.\n\n>   * If I visit a tag, and then decide I want to visit some other, more\n>     recent tag, I'm screwed because it obviously didn't exist in that\n>     old revision.  Tying tags to the revision history in this way is\n>     truly daft.\n\nIn git tags are direct or indirect (via tag object, creating annotated\ntag) pointers to points in revision history (in DAG of commits). Well,\nyou can tag any object, which is used for example in git.git to store\nout-of-tree junio GPG key used to sign release tags.\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"33395","messageId":"Pine.LNX.4.64.0702020835550.15057@woody.linux-foundation.org","threadId":"6583","inReplyTo":"epvnln$fmn$1@sea.gmane.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-02T16:42:05Z","receivedAt":"2007-02-02T16:42:05Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 2 Feb 2007, Jakub Narebski wrote:\n> \n> Gaaah. Why anyone would want to have non-propagated tags?\n\nThat's *definitely* not the mistake.\n\nI use private tags (and branches, for that matter) all the time. I'd be \nvery upset indeed if all my tags were always pushed out when I push \nsomething out.\n\nThe mistake seems to be to think that tags get \"versioned\", and are part \nof the tree history. That's insane. It means that you can never have a tag \nto a newer tree than the one you are on.\n\nTags are *independent* of history. They must be. They are \"outside\" \nhistory, since the whole point of tags are to point to history.\n\nThe same is obviously true of branches. The fact that my \"master\" branch \nis at some point in time should *not* version my \"other\" branch. So \nbranches - like tags - must not be \"inside\" the history.\n\n> > If I may be opinionated for a bit: this is barking for two reasons:\n> > \n> >   * The tags files grow by having lines added to the bottom.  Files of\n> >     this kind are almost ideal for causing merge conflicts, and there's\n> >     no automatic means for resolving them.  (I actually wrote a custom\n> >     tags merger recently -- if anyone wants it, just mail me.)\n> \n> Such a merger (merge strategy) would be also useful for other log-like\n> files, e.g. ChangeLogs and such.\n\nYeah. I think per-file merge strategies are fine. We may not do them in \ngit (nothing fundamental, it just hasn't come upas a real issue, although \nI think somebody was talking about how he ended up just using a special \n\"merge\" program that looked at the filename), but there is definitely \nnothing wrong with the concept.\n\nAnd it solves that particular problem for tag-files, but it doesn't change \nthe fact that keeping tags inside of history is insane in the first place \n(so it's not a problem that *should* be solved!)\n\n\t\t\tLinus\n"},{"id":"33396","messageId":"200702021759.22603.jnareb@gmail.com","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0702020835550.15057@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-02T16:59:22Z","receivedAt":"2007-02-02T16:59:22Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Linus Torvalds wrote:\n> \n> On Fri, 2 Feb 2007, Jakub Narebski wrote:\n>> \n>> Gaaah. Why anyone would want to have non-propagated tags?\n> \n> That's *definitely* not the mistake.\n\nErmmm... right. Now that I thought about it a bit...\n\n> I use private tags (and branches, for that matter) all the time. I'd be \n> very upset indeed if all my tags were always pushed out when I push \n> something out.\n\nWell, in git you can have private tags (anything not under refs/tags\nor under refs/heads is by default private), but I think you can only\nhave not published branches (which are not pushed to public repository).\nIf it is not true, then how one can have private branches \n(i.e. branches which 'push --all' would not push)?\n\n-- \nJakub Narebski\nPoland\n"},{"id":"33397","messageId":"Pine.LNX.4.64.0702020908150.15057@woody.linux-foundation.org","threadId":"6583","inReplyTo":"200702021759.22603.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-02T17:11:16Z","receivedAt":"2007-02-02T17:11:16Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 2 Feb 2007, Jakub Narebski wrote:\n> \n> Well, in git you can have private tags (anything not under refs/tags\n> or under refs/heads is by default private), but I think you can only\n> have not published branches (which are not pushed to public repository).\n> If it is not true, then how one can have private branches \n> (i.e. branches which 'push --all' would not push)?\n\nI have private branches, I just don't push them. The same thing is true of \ntags. \n\nAnybody who actually publishes his own git directory *directly* to pthers \nis probably insane. It's like showing your home directory. You just \nshouldn't do it. So anything in a real development archive is - by \ndefinition - \"private\". Only when you actually expose it explicitly (by \nexporting it at some public place) do things become public.\n\nBut if you tie your tags to history, you *have* to push them as you push \nthe history.\n\nSo again, this is not about private vs public. The bug is not there. The \nbug is thinking that you should make tags part of your history.\n\n\t\tLinus\n"},{"id":"33398","messageId":"200702021818.11368.jnareb@gmail.com","threadId":"6583","inReplyTo":"20070202160317.GX10108@waste.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-02T17:18:10Z","receivedAt":"2007-02-02T17:18:10Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On 02.02.2004, Matt Mackall wrote:\n> On Fri, Feb 02, 2007 at 10:55:48AM +0100, Jakub Narebski wrote:\n\n>> How Mercurial solves problem of multiple _persistent_ branches? Does it\n>> add pointers to commits somewhere deeper in changelog / revlog?\n> \n> Each changeset may have a branch marker.\n\nBy changeset you mean commit-revlog (changelog)? \n\nWhere those branch markers are stored? Are those markers moving pointers,\nmeaning that if you make a commit while on branch, branch marker for\ncurrent branch will move?\n\nStatic markers cannot identify branch in the presence of branch points:\n\n                   ---a<---b ........ side branch\n                  /\n  1<---2<---3<---4<---5<---6<---7 ... main branch\n            ^\n            :   \n             ''''' tag\n\n> Here's branches in use with an import of mutt's CVS history:\n> \n> $ hg branches\n> mutt-0-94                      208:b2cc0abd8fe0\n> HEAD                           207:a505693b54c1\n> mutt-0-93                      134:d59345944030\n> muttintl                       1:29510de8b3fc\n\nWhat is the first number? I understand that second is shortened (is it\nstored shortened, I wonder) hash identifier of a commit...\n\n> $ hg co HEAD\n> 176 files updated, 0 files merged, 8 files removed, 0 files unresolved\n\nGit (at least for now) writes nothing on checkout; it is planned that\nit would write changes status-like; perhaps summary would be enough...\nor is it only working area status that is to be written...\n\n> $ hg branch\n> HEAD\n> $ hg branch devel\n> $ hg branch\n> devel\n> $ hg branch devel\n> \n>> BTW does Mercurial have tags?\n> \n> Yes. Both local and revision-controlled.\n\nRevision-controlled (in-tree) tags are inane idea. Tags are non-moving\n(and sometimes annotated) pointers to given point in history. They should\nnot depend on which branch you are, or what version you have checked out.\n\nOtherwise the following would not work:\n $ git reset --hard v1.0.0\n $ git reset --hard v1.4.4.4\n(it could be \"git checkout\" instead of \"git reset --hard\" in 'master'\nversion of git, with \"detached HEAD\" / \"anonymous branch\" feature).\n\n>> Nice to know. You compress only file deltas, or also file revision\n>> metadata? Do you compress manifests (trees) and commits (or at least\n>> commit messages) too?\n> \n> All three use the same underlying storage format, so yes.\n\nBut do you compress metadata (like base of a delta for file deltas,\nauthorship of a commit and reference to manifest-log entry)? Do manifest\nis delta-encoded?\n\n-- \nJakub Narebski\nPoland\n"},{"id":"33400","messageId":"20070202173758.GC10108@waste.org","threadId":"6583","inReplyTo":"200702021818.11368.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Matt Mackall","fromEmail":"mpm@selenic.com","sentAt":"2007-02-02T17:37:58Z","receivedAt":"2007-02-02T17:37:58Z","isPatch":false,"sender":{"key":"mpm@selenic.com","avatar":null},"body":"On Fri, Feb 02, 2007 at 06:18:10PM +0100, Jakub Narebski wrote:\n> Revision-controlled (in-tree) tags are inane idea. Tags are non-moving\n> (and sometimes annotated) pointers to given point in history. They should\n> not depend on which branch you are, or what version you have checked out.\n\nAnd.. they don't!\n\nI'm now officially done correcting your uninformed perceptions. Come\nback when you've actually looked at the docs.\n\n-- \nMathematics is the supreme nostalgia of our time.\n"},{"id":"33402","messageId":"20070202175923.GA6304@xanadu.kublai.com","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0702020835550.15057@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Brendan Cully","fromEmail":"brendan@kublai.com","sentAt":"2007-02-02T17:59:23Z","receivedAt":"2007-02-02T17:59:23Z","isPatch":false,"sender":{"key":"brendan@kublai.com","avatar":null},"body":"On Friday, 02 February 2007 at 08:42, Linus Torvalds wrote:\n> \n> \n> On Fri, 2 Feb 2007, Jakub Narebski wrote:\n> > \n> > Gaaah. Why anyone would want to have non-propagated tags?\n> \n> That's *definitely* not the mistake.\n> \n> I use private tags (and branches, for that matter) all the time. I'd be \n> very upset indeed if all my tags were always pushed out when I push \n> something out.\n> \n> The mistake seems to be to think that tags get \"versioned\", and are part \n> of the tree history. That's insane. It means that you can never have a tag \n> to a newer tree than the one you are on.\n\nThe tags you use can simply be those from the tip of the repository,\nregardless of which revision you've currently checked out.\n\n> Tags are *independent* of history. They must be. They are \"outside\" \n> history, since the whole point of tags are to point to history.\n\nTags have history too. They are added at particular times by\nparticular people, and sometimes changed (this wouldn't happen in an\nideal world, but it happens). It's a shame not to be able to find this\nhistory.\n"},{"id":"33403","messageId":"200702021919.28669.jnareb@gmail.com","threadId":"6583","inReplyTo":"20070202175923.GA6304@xanadu.kublai.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-02T18:19:28Z","receivedAt":"2007-02-02T18:19:28Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Brendan Cully wrote:\n> On Friday, 02 February 2007 at 08:42, Linus Torvalds wrote:\n>> \n>> The mistake seems to be to think that tags get \"versioned\", and are part \n>> of the tree history. That's insane. It means that you can never have a tag \n>> to a newer tree than the one you are on.\n> \n> The tags you use can simply be those from the tip of the repository,\n> regardless of which revision you've currently checked out.\n\n_Can_ be or _are_ (in Mercurial)? Besides, there can be more than one\ntip of repository (branch are tips of history), and making set of tags\ndependent on which branch you are on is not a good idea either.\n\n>> Tags are *independent* of history. They must be. They are \"outside\" \n>> history, since the whole point of tags are to point to history.\n> \n> Tags have history too. They are added at particular times by\n> particular people, and sometimes changed (this wouldn't happen in an\n> ideal world, but it happens). It's a shame not to be able to find this\n> history.\n\nThat is what reflogs are for, although you usually don't enable this\nfor tags (because tags are meant to be immutable, especially signed\nrelease tags).\n\nBesides, in git annotated tags have tagger info, i.e. who and when\ncreated a tag.\n\n\nBesides tags point to history. Having them inside history is abstraction\nbreakage, IMVHO.\n-- \nJakub Narebski\nPoland\n"},{"id":"33404","messageId":"20070202182709.GA3861@kobe.laptop","threadId":"6583","inReplyTo":"20070202175923.GA6304@xanadu.kublai.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Giorgos Keramidas","fromEmail":"keramida@ceid.upatras.gr","sentAt":"2007-02-02T18:27:10Z","receivedAt":"2007-02-02T18:27:10Z","isPatch":false,"sender":{"key":"keramida@ceid.upatras.gr","avatar":null},"body":"On 2007-02-02 09:59, Brendan Cully <brendan@kublai.com> wrote:\n>On Friday, 02 February 2007 at 08:42, Linus Torvalds wrote:\n>> Tags are *independent* of history. They must be. They are \"outside\"\n>> history, since the whole point of tags are to point to history.\n>\n> Tags have history too. They are added at particular times by\n> particular people, and sometimes changed (this wouldn't happen in an\n> ideal world, but it happens). It's a shame not to be able to find this\n> history.\n\nAgreed.  There is a _reason_ behind the -f option of 'cvs tag'.\n\nSometimes, 'sliding a tag' is a real-world need.  Losing the information\nof who did the tag sliding and when, is not good.\n"},{"id":"33405","messageId":"Pine.LNX.4.64.0702021027450.15057@woody.linux-foundation.org","threadId":"6583","inReplyTo":"20070202175923.GA6304@xanadu.kublai.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-02T18:32:17Z","receivedAt":"2007-02-02T18:32:17Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 2 Feb 2007, Brendan Cully wrote:\n\n> On Friday, 02 February 2007 at 08:42, Linus Torvalds wrote:\n> > \n> > \n> > On Fri, 2 Feb 2007, Jakub Narebski wrote:\n> > > \n> > > Gaaah. Why anyone would want to have non-propagated tags?\n> > \n> > That's *definitely* not the mistake.\n> > \n> > I use private tags (and branches, for that matter) all the time. I'd be \n> > very upset indeed if all my tags were always pushed out when I push \n> > something out.\n> > \n> > The mistake seems to be to think that tags get \"versioned\", and are part \n> > of the tree history. That's insane. It means that you can never have a tag \n> > to a newer tree than the one you are on.\n> \n> The tags you use can simply be those from the tip of the repository,\n> regardless of which revision you've currently checked out.\n\nDid you not understand the problem?\n\nIf I want to push out my history, that does NOT mean that I don't want to \npush out my tags. At least not to the public sites. I migth want to push \nthem out to my other *private* copies, though.\n\nIn other words, tags are just like branches. You don't tie two tags \ntogether, because one may (and does) make sense without the other.\n\nTying tags into history is silly. They're not \"part of\" history. They are \npointers *to* history. And trying to make them part of history has all \nthese obvious problems.\n\n\t\t\tLinus\n"},{"id":"33407","messageId":"200702021944.14756.jnareb@gmail.com","threadId":"6583","inReplyTo":"20070202173758.GC10108@waste.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-02T18:44:13Z","receivedAt":"2007-02-02T18:44:13Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Matt Mackall wrote:\n> On Fri, Feb 02, 2007 at 06:18:10PM +0100, Jakub Narebski wrote:\n\n>> Revision-controlled (in-tree) tags are inane idea. Tags are non-moving\n>> (and sometimes annotated) pointers to given point in history. They should\n>> not depend on which branch you are, or what version you have checked out.\n> \n> And.. they don't!\n\nIf that means that you always use the version of .hgtags from the tip\n(branches are tips of history; they can have different .hgtags),\nthis is also broken; this means for example that you cannot compare\ncurrent version when on development head (branch) with tag on different\nbranch, those two branches have the same .hgtags file.\n\n\"They should not depend on which branch you are\"... and they can.\n\n> I'm now officially done correcting your uninformed perceptions. Come\n> back when you've actually looked at the docs.\n\nURL, pretty please?\n\nMy mistake is caused by the fact that .hgtags is special, i.e. not\ncurrent version is used (as e.g. with .scmignore files) but version\nclosest to the tip. This means broken abstraction.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"33406","messageId":"Pine.LNX.4.64.0702021050350.15057@woody.linux-foundation.org","threadId":"6583","inReplyTo":"20070202182709.GA3861@kobe.laptop","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-02T19:01:08Z","receivedAt":"2007-02-02T19:01:08Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 2 Feb 2007, Giorgos Keramidas wrote:\n> \n> Sometimes, 'sliding a tag' is a real-world need.  Losing the information\n> of who did the tag sliding and when, is not good.\n\nIn practice, this is not much of an issue. \n\nFirst off, CVS tag usage is insane, but it's insane for *other* reasons \n(ie people use tags differently in CVS, but they do it not because they \nwant to use tags that way, but because CVS makes it impossible to do \nanything saner).\n\nSo pointing to CVS tag usage as an argument is pointless. You might as \nwell say that you shouldn't save the merge information, because CVS \ndoesn't do it, and manual tags are a good way to do it. \n\nSecondly, the problems with tags having \"history\" is that you can't really \nresolve them anyway. You have to pick one. You can't \"merge\" them. \n\nIn other words, tags are atomic *events*, not history. And I certainly \nagree that you shouldn't lose the events (unless you want to, of course).\n\nI also do agree that you can absolutely have something that is basically a \n\"tag that moves, and that you want to tie back to the previous state of \nthe tag\". In git, we just happen to call those things \"branches\". You \n*could* technically put one of those things into the tag-namespace if you \nwant to, although it would largely be considered insane by most git users \n(and you could see it historically: each \"tag\" would be a merge that \npoints to its previous incarnation and to the point in time that got \ntagged).\n\nMore commonly, you'd just use a \"real tag\", which includes the tagger \ninformation and a message about why something got tagged, plus possibly a \nPGP signature. That way, you can see (and save) all the individual events.\n\n\t\tLinus\n"},{"id":"33408","messageId":"20070202192640.GA7963@ventoux.cs.ubc.ca","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0702021027450.15057@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Brendan Cully","fromEmail":"brendan@kublai.com","sentAt":"2007-02-02T19:26:40Z","receivedAt":"2007-02-02T19:26:40Z","isPatch":false,"sender":{"key":"brendan@kublai.com","avatar":null},"body":"On Friday, 02 February 2007 at 10:32, Linus Torvalds wrote:\n> \n> \n> On Fri, 2 Feb 2007, Brendan Cully wrote:\n> \n> > On Friday, 02 February 2007 at 08:42, Linus Torvalds wrote:\n> > > \n> > > \n> > > On Fri, 2 Feb 2007, Jakub Narebski wrote:\n> > > > \n> > > > Gaaah. Why anyone would want to have non-propagated tags?\n> > > \n> > > That's *definitely* not the mistake.\n> > > \n> > > I use private tags (and branches, for that matter) all the time. I'd be \n> > > very upset indeed if all my tags were always pushed out when I push \n> > > something out.\n> > > \n> > > The mistake seems to be to think that tags get \"versioned\", and are part \n> > > of the tree history. That's insane. It means that you can never have a tag \n> > > to a newer tree than the one you are on.\n> > \n> > The tags you use can simply be those from the tip of the repository,\n> > regardless of which revision you've currently checked out.\n> \n> Did you not understand the problem?\n> \n> If I want to push out my history, that does NOT mean that I don't want to \n> push out my tags. At least not to the public sites. I migth want to push \n> them out to my other *private* copies, though.\n\nI don't think I do, no. (Maybe it's the double negative construction.)\nLocal tags don't get pushed. Tags on private branches don't get\npushed. Tags on public branches do. This business you describe, where\nyou push tags around completely separate from the revisions they tag,\nsounds a little odd. But nothing stops you from maintaining your local\ntags in their own repository, if that's what makes you happy.\n\n> In other words, tags are just like branches. You don't tie two tags \n> together, because one may (and does) make sense without the other.\n\nWhich tags are being tied together?\n\n> Tying tags into history is silly. They're not \"part of\" history. They are \n> pointers *to* history. And trying to make them part of history has all \n> these obvious problems.\n\nIt seems to me they clearly do have history.\n"},{"id":"33409","messageId":"20070202192829.GB7963@ventoux.cs.ubc.ca","threadId":"6583","inReplyTo":"200702021919.28669.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Brendan Cully","fromEmail":"brendan@kublai.com","sentAt":"2007-02-02T19:28:29Z","receivedAt":"2007-02-02T19:28:29Z","isPatch":false,"sender":{"key":"brendan@kublai.com","avatar":null},"body":"On Friday, 02 February 2007 at 19:19, Jakub Narebski wrote:\n> Brendan Cully wrote:\n> > On Friday, 02 February 2007 at 08:42, Linus Torvalds wrote:\n> >> \n> >> The mistake seems to be to think that tags get \"versioned\", and are part \n> >> of the tree history. That's insane. It means that you can never have a tag \n> >> to a newer tree than the one you are on.\n> > \n> > The tags you use can simply be those from the tip of the repository,\n> > regardless of which revision you've currently checked out.\n> \n> _Can_ be or _are_ (in Mercurial)? Besides, there can be more than one\n\nare. The meaning of tags depends on the repository, not the \"index\".\n\n> tip of repository (branch are tips of history), and making set of tags\n> dependent on which branch you are on is not a good idea either.\n\nagreed.\n"},{"id":"33411","messageId":"Pine.LNX.4.64.0702021130020.15057@woody.linux-foundation.org","threadId":"6583","inReplyTo":"20070202192640.GA7963@ventoux.cs.ubc.ca","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-02T19:42:30Z","receivedAt":"2007-02-02T19:42:30Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 2 Feb 2007, Brendan Cully wrote:\n> \n> I don't think I do, no. (Maybe it's the double negative construction.)\n> Local tags don't get pushed. Tags on private branches don't get\n> pushed. Tags on public branches do. This business you describe, where\n> you push tags around completely separate from the revisions they tag,\n> sounds a little odd. But nothing stops you from maintaining your local\n> tags in their own repository, if that's what makes you happy.\n> \n> > In other words, tags are just like branches. You don't tie two tags \n> > together, because one may (and does) make sense without the other.\n> \n> Which tags are being tied together?\n\nIf you tie \"tag\" together with \"history\", and push out history, what \nhappens?\n\n> It seems to me they clearly do have history.\n\nNo they don't. Quite often, tags are generated outside of history, ie you \ntag something as being \"known bad\" long after it was done. Or you \n(hopefully) tag it with the test-information after it passed (or \ndidn't) pass some debug check. Neither of which is something you'd do when \nthe thing is actually committed or developed.\n\nSo tags are *events*. But if you think they are events \"within\" the \nhistory of a tree, you're missing a big issue.\n\nMy personal use of tags tends to be\n - I tag releases I make, and sign them etc.\n - when debugging (and using \"git bisect\" in particular), I tag things for \n   my own memory (ie if a bisection selected something that didn't \n   compile, and I have to pick another point by hand, I tag that bad one \n   temporarily for explanation - the tag shows up nicely in the graphical \n   history viewers)\n\nThe \"release\" tags are done as I develop, since _others_ will do \nregression tests etc later on. I don't know whether those others will add \ntheir own tags on top of my tag (\"passed-regression-test\" tag that points \nto my release-tag, which points to whatever commit I released), but it's \nreally worth pointing out that that is just a small special case.\n\nThat *small* special case I wouldn't mind being part of history. But all \nthe other tags should never be, since they are actually personal to \nwhoever made them (even though others may well care: for example, if a \nregression run tags something as \"passed\", a lot of people will care: it \ndoesn't mean that the tag should be entirely private!).\n\nAnd because it's wrong in general to make the tags be bound to history \n(because they may or may not be relevant to others, and they may or may \nnot actually happen _during_ the history), it's wrong to design the tags \nthat way. Tags really are \"outside\" the thing, unless you live in a world \nwhere only the lead engineer is supposed to use tags.\n\nI want tags to be useful for *anybody*. A total non-developer, who decides \nthat he wants to test a release, should be able to tag the particular \nversions he happened to test, and it damn well shouldn't be just \n\"my-tag-1023\". It should allow him to write a small story about what the \nresults of the tests were!\n\nWhich is how git tags are desiged. They're separate from history, but that \ndoesn't make them less useful - it makes them *more* widely useful.\n\n\t\tLinus\n"},{"id":"33412","messageId":"20070202195504.GC7963@ventoux.cs.ubc.ca","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0702021130020.15057@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Brendan Cully","fromEmail":"brendan@kublai.com","sentAt":"2007-02-02T19:55:05Z","receivedAt":"2007-02-02T19:55:05Z","isPatch":false,"sender":{"key":"brendan@kublai.com","avatar":null},"body":"On Friday, 02 February 2007 at 11:42, Linus Torvalds wrote:\n> \n> \n> On Fri, 2 Feb 2007, Brendan Cully wrote:\n> > \n> > I don't think I do, no. (Maybe it's the double negative construction.)\n> > Local tags don't get pushed. Tags on private branches don't get\n> > pushed. Tags on public branches do. This business you describe, where\n> > you push tags around completely separate from the revisions they tag,\n> > sounds a little odd. But nothing stops you from maintaining your local\n> > tags in their own repository, if that's what makes you happy.\n> > \n> > > In other words, tags are just like branches. You don't tie two tags \n> > > together, because one may (and does) make sense without the other.\n> > \n> > Which tags are being tied together?\n> \n> If you tie \"tag\" together with \"history\", and push out history, what \n> happens?\n\nThe public tags on the public history get pushed. This still sounds to\nme like the right thing.\n\n> > It seems to me they clearly do have history.\n> \n> No they don't. Quite often, tags are generated outside of history, ie you \n> tag something as being \"known bad\" long after it was done. Or you \n> (hopefully) tag it with the test-information after it passed (or \n> didn't) pass some debug check. Neither of which is something you'd do when \n> the thing is actually committed or developed.\n>\n> So tags are *events*. But if you think they are events \"within\" the \n> history of a tree, you're missing a big issue.\n\nYour distinction between \"history\" and \"events\" is unclear to\nme. What's history if not a series of events?\n\nJust because a tag is created at a different time than the revision it\ntags, that doesn't mean that it is ahistorical. It's still interesting\nto know what the state of the repository was when the tag was\ncreated.\n\n> My personal use of tags tends to be\n>  - I tag releases I make, and sign them etc.\n>  - when debugging (and using \"git bisect\" in particular), I tag things for \n>    my own memory (ie if a bisection selected something that didn't \n>    compile, and I have to pick another point by hand, I tag that bad one \n>    temporarily for explanation - the tag shows up nicely in the graphical \n>    history viewers)\n\nMercurial supports local tags too. As far as I can tell, these\nunversioned tags are about equivalent to git tags. They could\ncertainly be used for your bisection scenario.\n\n> I want tags to be useful for *anybody*. A total non-developer, who decides \n> that he wants to test a release, should be able to tag the particular \n> versions he happened to test, and it damn well shouldn't be just \n> \"my-tag-1023\". It should allow him to write a small story about what the \n> results of the tests were!\n> \n> Which is how git tags are desiged. They're separate from history, but that \n> doesn't make them less useful - it makes them *more* widely useful.\n\nMercurial supports both, because both are useful.\n"},{"id":"33413","messageId":"200702022056.32791.jnareb@gmail.com","threadId":"6583","inReplyTo":"200702021944.14756.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-02T19:56:31Z","receivedAt":"2007-02-02T19:56:31Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jakub Narebski wrote:\n> Matt Mackall wrote:\n>> On Fri, Feb 02, 2007 at 06:18:10PM +0100, Jakub Narebski wrote:\n> \n>>> Revision-controlled (in-tree) tags are inane idea. Tags are non-moving\n>>> (and sometimes annotated) pointers to given point in history. They should\n>>> not depend on which branch you are, or what version you have checked out.\n>> \n>> And.. they don't!\n> \n> If that means that you always use the version of .hgtags from the tip\n> (branches are tips of history; they can have different .hgtags),\n> this is also broken; this means for example that you cannot compare\n> current version when on development head (branch) with tag on different\n> branch, those two branches have the same .hgtags file.\n\nI meant to write:\n\n..._unless_ those two branches have the same .hgtags file.\n\n> \"They should not depend on which branch you are\"... and they can.\n\nFor example you are on branch 'master', you tag current release\ne.g. v1.3.4, then you checkout branch 'devel'... and you don't have\nv1.3.4 tag available unless you merge in .hgtags from 'master'.\nAt least from what I understand of Mercurial tags behaviour.\n\nHaving to create a commit to remember tag which can be published...\nI'm not sure if it is a good idea either. Junio creates \"GIT 1.4.4.3\"\ncommits, ant those are tagges, so perhaps it is not so bad idea\neither.\n\nYou encourage to hand-edit .hgtags, but the edited version might\nnot be the one that is used (for example when starting a branch).\n\n-- \nJakub Narebski\nPoland\n"},{"id":"33414","messageId":"200702022115.31571.jnareb@gmail.com","threadId":"6583","inReplyTo":"20070202195504.GC7963@ventoux.cs.ubc.ca","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-02T20:15:31Z","receivedAt":"2007-02-02T20:15:31Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Brendan Cully wrote:\n\n> Just because a tag is created at a different time than the revision it\n> tags, that doesn't mean that it is ahistorical. It's still interesting\n> to know what the state of the repository was when the tag was\n> created.\n\nI think not. Why would one want to know what was the state of the \nrepository when the tag (perhaps to some historical, old commit)\nwas created?\n\n-- \nJakub Narebski\nPoland\n"},{"id":"33415","messageId":"Pine.LNX.4.64.0702021214260.15057@woody.linux-foundation.org","threadId":"6583","inReplyTo":"20070202195504.GC7963@ventoux.cs.ubc.ca","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-02T20:21:24Z","receivedAt":"2007-02-02T20:21:24Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 2 Feb 2007, Brendan Cully wrote:\n> \n> The public tags on the public history get pushed. This still sounds to\n> me like the right thing.\n\nAnd what happens if you have two public tags?\n\nOk, now you have answered the \"how is this tying them together\" question \nyourself.\n\nNotice? You tied them together, by tying them to something else.\n\nAnd that is what I say is WRONG. Tags are independent, because different \npeople have different needs for them.\n\nYes, you can say that the tags that the \"main developer\" does are \"magic\", \nand should always follow the history. But EVEN THAT is wrong. Because it \nmakes a supposition that should not be one. You shouldn't start out with \nthe assumption that there is one centralized place that makes the \ndecisions. It may be how most open source projects work, but it's not what \nthe tool should enforce. Especially when projects break/fork/whatever, the \ntool should _support_ that. It shouldn't say \"ok, those people are \nspecial, what they do is special\".\n\n> > So tags are *events*. But if you think they are events \"within\" the \n> > history of a tree, you're missing a big issue.\n> \n> Your distinction between \"history\" and \"events\" is unclear to\n> me. What's history if not a series of events?\n\nA lot of events are *independent*.\n\nYou seem to think that there is a dependency between tags that simply \nisn't there! You think it's ok to push them all out, because they are all \n\"related\". THAT IS NOT TRUE.\n\n> Mercurial supports local tags too. As far as I can tell, these\n> unversioned tags are about equivalent to git tags. They could\n> certainly be used for your bisection scenario.\n\nCan you push out your local tags? \n\nA tag isn't \"globally local\" or \"globally global\". *MY* local tags make \nsense on my machines. It's just that they don't make sense on the public \ntree. They're not \"local to a repository\". They are LOCAL TO MY NETWORK.\n\nSee? That's the kind of behaviour that git supports. You can publish one \nset of tags, and not publish another. They're not \"different tags\", and \nnot publishing them in one place does NOT mean that you can't publish them \nsomewhere else.\n\n\t\tLinus\n"},{"id":"33474","messageId":"20070203200638.GA6888@xanadu.kublai.com","threadId":"6583","inReplyTo":"200702022056.32791.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Brendan Cully","fromEmail":"brendan@kublai.com","sentAt":"2007-02-03T20:06:39Z","receivedAt":"2007-02-03T20:06:39Z","isPatch":false,"sender":{"key":"brendan@kublai.com","avatar":null},"body":"On Friday, 02 February 2007 at 20:56, Jakub Narebski wrote:\n> For example you are on branch 'master', you tag current release\n> e.g. v1.3.4, then you checkout branch 'devel'... and you don't have\n> v1.3.4 tag available unless you merge in .hgtags from 'master'.\n> At least from what I understand of Mercurial tags behaviour.\n\nThis would be bad, if it were true.\n\n$ hg up devel\n2 files updated, 0 files merged, 0 files removed, 0 files unresolved\n$ cat .hgtags\n6acda9aa5d8c621b3db2f2daab878d8de726d227 base\n$ hg tags\ntip                                4:b1f003583d8e\nv1.3.4                             2:87e43e86318f\nbase                               0:6acda9aa5d8c\n\nAs mentioned before, hg has local tags which sound an awful lot like\ngit tags. It also has properly versioned tags. And, by the way, if you\npush a branch, you only push the tags that were committed on that\nbranch. Furthermore, you can push based on a tag name that isn't\ncommitted in the branch you're pushing. I think the \"globally global\"\nnonsense elsewhere in this thread may be a result of not understanding\nthis.\n\nI'm probably done with this thread too. There's too much ignorant\nspeculation to make it very productive.\n"},{"id":"33480","messageId":"200702032155.16987.jnareb@gmail.com","threadId":"6583","inReplyTo":"20070203200638.GA6888@xanadu.kublai.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-03T20:55:15Z","receivedAt":"2007-02-03T20:55:15Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On 03.02.2007, Brendan Cully <brendan@kublai.com> wrote:\n> On Friday, 02 February 2007 at 20:56, Jakub Narebski wrote:\n\n>> For example you are on branch 'master', you tag current release\n>> e.g. v1.3.4, then you checkout branch 'devel'... and you don't have\n>> v1.3.4 tag available unless you merge in .hgtags from 'master'.\n>> At least from what I understand of Mercurial tags behaviour.\n> \n> This would be bad, if it were true.\n> \n> $ hg up devel\n> 2 files updated, 0 files merged, 0 files removed, 0 files unresolved\n> $ cat .hgtags\n> 6acda9aa5d8c621b3db2f2daab878d8de726d227 base\n> $ hg tags\n> tip                                4:b1f003583d8e\n> v1.3.4                             2:87e43e86318f\n> base                               0:6acda9aa5d8c\n\nThe above sequence of commands is not enough to reproduce the situation\nI want to talk about, namely situation (repository structure) as in \nbelow:\n\n                    /-\\ \n   1---a---2---3---T---t---b   .... 'master' branch\n        \\ \n         \\-2'--3'--c           .... 'devel' branch\n\nwhere 'a' is branching point (merge base) of 'master' and 'devel' \nbranches, 'T' is tagged changeset (revision, commit), 't' is commit\nwhere .hgtags with 'T' tag was committed. Changesets (revisions)\n'b' and 'c' are tips of 'master' and 'devel' branch, respectively.\n\nIf .hgtags was an ordinary file, then at revision marked in above\ngraph as '2' it wouldn't have tag 'T'.  Documentation (Mercurial\nHOWTO to be more exact) tells that hg uses .hgtags version from the\ntip.  But when we are at branch 'devel', the version from the tip\nis version 'c' without 'T', not version 'b' with 'T'... if .hgtags\nwould behave as described in documentation.\n\nIt looks however (if what you say above is true also for the situation \nas in above graph, i.e. when at 'devel' branch we have 'T' in .hgtags)\nthat Mercurial always uses _latest_ version of .hgtags file (as in \nexternal wall time, having notihing to do with the history as \nrepresented in repository). But then we cannot say that we can merge\n.hgtags file, so it is probably not the case. It is also contrary to \nwhat I gathered from documentation.\n\nIf above was true, i.e. .hgtags doesn't behave at all as normal file in \nworking area, then what the heck it is doing there, and not somewhere \nunder .hgtags!?!\n\n> As mentioned before, hg has local tags which sound an awful lot like\n> git tags. \n\nGit tags can be propagated. hg local tags cannot be propagated. hg tags \n\"in history\" always are propagated.\n\n> It also has properly versioned tags.\n\nReusing in-tree version control to version tags is IMVHO not a good \nidea. Git has reflogs if you truly need to have history of tags.\n\n> And, by the way, if you  \n> push a branch, you only push the tags that were committed on that\n> branch. Furthermore, you can push based on a tag name that isn't\n> committed in the branch you're pushing. \n\nIt seems awfully complicated.\n\n> I think the \"globally global\" \n> nonsense elsewhere in this thread may be a result of not understanding\n> this.\n> \n> I'm probably done with this thread too. There's too much ignorant\n> speculation to make it very productive.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"33483","messageId":"200702032200.11070.jnareb@gmail.com","threadId":"6583","inReplyTo":"200702032155.16987.jnareb@gmail.com","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-03T21:00:10Z","receivedAt":"2007-02-03T21:00:10Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jakub Narebski wrote:\n[...] \n> If above was true, i.e. .hgtags doesn't behave at all as normal file in \n> working area, then what the heck it is doing there, and not somewhere \n> under .hgtags!?!\n\nI meant: not somewhere under .hg/ (in repository, and not in working area,\nif it does not behave as an ordinary working area file)\n-- \nJakub Narebski\nPoland\n"},{"id":"33486","messageId":"20070203212030.GA91453@kobe.laptop","threadId":"6583","inReplyTo":"Pine.LNX.4.64.0702021050350.15057@woody.linux-foundation.org","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Giorgos Keramidas","fromEmail":"keramida@ceid.upatras.gr","sentAt":"2007-02-03T21:20:30Z","receivedAt":"2007-02-03T21:20:30Z","isPatch":false,"sender":{"key":"keramida@ceid.upatras.gr","avatar":null},"body":"On 2007-02-02 11:01, Linus Torvalds <torvalds@linux-foundation.org> wrote:\n>On Fri, 2 Feb 2007, Giorgos Keramidas wrote:\n>> Sometimes, 'sliding a tag' is a real-world need.  Losing the\n>> information of who did the tag sliding and when, is not good.\n>\n> In practice, this is not much of an issue.\n\nSure it is.  Maybe not in the context of all projects or all teams, but\nproperly versioning tag names and knowing who installed the tag, and\nwhen is quite often an issue with unversioned tags in some of the teams\nI have worked with.\n\n> First off, CVS tag usage is insane, but it's insane for *other*\n> reasons (ie people use tags differently in CVS, but they do it not\n> because they want to use tags that way, but because CVS makes it\n> impossible to do anything saner).\n>\n> So pointing to CVS tag usage as an argument is pointless. You might as\n> well say that you shouldn't save the merge information, because CVS\n> doesn't do it, and manual tags are a good way to do it.\n>\n> Secondly, the problems with tags having \"history\" is that you can't\n> really resolve them anyway. You have to pick one. You can't \"merge\"\n> them.\n\nOk, maybe CVS was not so good as an example of why versioned tags *are*\nuseful, but my comment came from the experience I have with the tagging\nof FreeBSD release builds.  The -STABLE branch os FreeBSD may be tagged\nwith RELENG_X_Y_Z_RELEASE at a particular point in time.  If we find\nthat some important bug fix has to go in, the fix is committed, and the\ntag can 'slide' forward for only a particular file or set of files.\n\nWhen tags are versioned, this operation is properly versioned too.  It's\napparent from browsing the global tag history that the specific tag\n*was* moved forward; it's obvious where it was pointing before the\n'slide' operation; it's obvious which files the 'slide' affected, etc.\n\nHaving the tags operations as an integral part of the visible history of\nall public repositories is not necessarily useful for 100% of the\npeople who may skim through the logs, but I'm not sure why you suggest\nthat it's difficult to \"merge\" tags.\n\nSince tags point to a very specific changeset hash, the hash serves as a\nunique, unconflicting identifier of the tag's location in history.  When\na \"pull\" operation happens, there are no conflicts unless there is a\nnaming conflict between the \"remote\" and \"local\" repository.  It's not\nimpossible or even difficult to \"merge\" the two tag sets.\n\n> In other words, tags are atomic *events*, not history. And I certainly\n> agree that you shouldn't lose the events (unless you want to, of course).\n\nTags are a little of two different things:\n\n(1) They are 'events' in the sense that someone has placed them to a\ntree, and this operation is a very real, very natural event, and *this*\nevent should be versioned.\n\n(2) They are 'pointers' to a particular changeset id.  The particular\nchangeset hash to which they point, when the user looks at a specific\nrevision of the history tree, is immuttable from the point of view of\nsomeone looking at this specific revision.  It may *change* as the\nviewer moves back and forth into the history tree though.\n\nThe pointer-nature of tags doesn't need to be versioned when one looks\nat one particular changeset, but the event-nature of their placement\ninto the tree *can* be versioned and IMHO it *should* be versioned.\nOtherwise, there is no good way to provide accountability for these\nevents, and some part of the repository 'history' is lost.\n\n> I also do agree that you can absolutely have something that is\n> basically a \"tag that moves, and that you want to tie back to the\n> previous state of the tag\". In git, we just happen to call those\n> things \"branches\".\n\nYou're confusing a single, one-time movement of a tag (to point to a\nplace *after* a bugfix, for instance), with the creation of a new,\nentirely separate, full branch.  One of them is ok in some cases; the\nother is probably necessary in others.\n\nI can understand why they don't _both_ seem useful for all possible\ncases, but I don't see why we should limit ourselves to only one of the\ntwo options.\n\n- Giorgos\n"},{"id":"33489","messageId":"1170538625.7564.12.camel@localhost.localdomain","threadId":"6583","inReplyTo":"20070203212030.GA91453@kobe.laptop","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Matthias Kestenholz","fromEmail":"lists@spinlock.ch","sentAt":"2007-02-03T21:37:04Z","receivedAt":"2007-02-03T21:37:04Z","isPatch":false,"sender":{"key":"lists@spinlock.ch","avatar":null},"body":"On Sat, 2007-02-03 at 23:20 +0200, Giorgos Keramidas wrote:\n> Ok, maybe CVS was not so good as an example of why versioned tags *are*\n> useful, but my comment came from the experience I have with the tagging\n> of FreeBSD release builds.  The -STABLE branch os FreeBSD may be tagged\n> with RELENG_X_Y_Z_RELEASE at a particular point in time.  If we find\n> that some important bug fix has to go in, the fix is committed, and the\n> tag can 'slide' forward for only a particular file or set of files.\n> \n\nThis operation is seriously broken. The Z number should be incremented,\nthe tag should continue pointing at the (now known to be) broken\nversion. That's exactly what the patchlevel number is for.\n\nIf users want to know if there are important security updates around,\nthey will look at the version number. If you change the revision which\nthe tag points to you will _seriously_ confuse users, a lot more than a\nlong list of patchlevel versions will ever do.\n\nMatthias\n"},{"id":"33490","messageId":"Pine.LNX.4.64.0702031334400.8424@woody.linux-foundation.org","threadId":"6583","inReplyTo":"20070203212030.GA91453@kobe.laptop","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-03T21:41:46Z","receivedAt":"2007-02-03T21:41:46Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 3 Feb 2007, Giorgos Keramidas wrote:\n> \n> Sure it is.  Maybe not in the context of all projects or all teams, but\n> properly versioning tag names and knowing who installed the tag, and\n> when is quite often an issue with unversioned tags in some of the teams\n> I have worked with.\n\nI don't understand why you argue. Everybody agrees. This is not what I've \nbeen arguing against.\n\nGit tags too (unless you are lazyor just don't _want_ to version them) are \nversioned. It's the whole reason why git has a whole separate \"tag space\". \nNot only that, but they are evencryptographically signed (again, this is \nnot forced on you, but it's part of standard practice in git projects) \nwith an author key, so that the tag actually says a lot more than just the \nversion - it also gives you authenticity guarantees.\n\nIn the gitk history viewer, when you click on the tag, it will show you \nthat. It will show you who tagged it, and when, and if two people tag with \nthe same tag-name (or the same person renames a tag), you can use that to \nsee which one you have.\n\nSo nobody disputes at all that it's good to see that kind of detail.\n\nWhat I claim is simple: tags are independent of history. The fact that you \nhave the history, doesn't necessarily mean that you should have the tag. \nBecause some tags make sense for some people.\n\nAnd it's *not* about being private to a repository. The relevance simply \nisn't a black-and-white \"one repo or all repos\" kind of choice. For \nexample, you might have private tags within a company, and not choose to \nexport those outside of the company. \n\n\t\tLinus\n"},{"id":"33491","messageId":"200702032245.34087.jnareb@gmail.com","threadId":"6583","inReplyTo":"20070203212030.GA91453@kobe.laptop","subject":"Re: newbie questions about git design and features (some wrt hg)","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-02-03T21:45:33Z","receivedAt":"2007-02-03T21:45:33Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On 03-02-2007, Giorgos Keramidas wrote:\n> On 2007-02-02 11:01, Linus Torvalds <torvalds@linux-foundation.org> wrote:\n>>On Fri, 2 Feb 2007, Giorgos Keramidas wrote:\n\n>>> Sometimes, 'sliding a tag' is a real-world need.  Losing the\n>>> information of who did the tag sliding and when, is not good.\n>>\n>> In practice, this is not much of an issue.\n> \n> Sure it is.  Maybe not in the context of all projects or all teams, but\n> properly versioning tag names and knowing who installed the tag, and\n> when is quite often an issue with unversioned tags in some of the teams\n> I have worked with.\n\nKnowing who installed (made) a tag, and when is totally separate issue\nfrom versioning tag names. In git first (along with tag description,\nand optional PGP signing of tag) is solved by using tag objects, it\nmeans indirect pointers: name like v1.4.0 (refs/tags/v1.4.0) refers\nto tag object, which looks like below:\n\n  object 41292ddd37202ff6dce34986c87a6000c5d3fbfa\n  type commit\n  tag v1.4.0\n  tagger Junio C Hamano <junkio@cox.net> Sat Jun 10 12:43:37 2006 -0700\n  \n  GIT 1.4.0\n  -----BEGIN PGP SIGNATURE-----\n  Version: GnuPG v1.4.3 (GNU/Linux)\n  \n  iD8DBQBEiyDswMbZpPMRm5oRAr5KAJ95nnyY8x7nRVIxkV87AHux6Kdf2gCgi4xu\n  NxK2qKsAkGXCil7zSFviawA=\n  =Qhax\n  -----END PGP SIGNATURE-----\n \n\nSecond, [local] versioning tags (if it is really needed, see discussion\nbelow)  is solved using reflogs for tags, which look like below:\n\n000000... fab4f1... Jakub Narebski <jnareb@gmail.com> 1163751632 +0100 \\\n    fetch origin git://git.kernel.org/pub/scm/git/git.git: storing tag\n\n(it is in single line, broken here for better readibility). It is local\nhistory; I don't thing global history of tags is needed (see below).\n\n>> First off, CVS tag usage is insane, but it's insane for *other*\n>> reasons (ie people use tags differently in CVS, but they do it not\n>> because they want to use tags that way, but because CVS makes it\n>> impossible to do anything saner).\n>>\n>> So pointing to CVS tag usage as an argument is pointless. You might as\n>> well say that you shouldn't save the merge information, because CVS\n>> doesn't do it, and manual tags are a good way to do it.\n>>\n>> Secondly, the problems with tags having \"history\" is that you can't\n>> really resolve them anyway. You have to pick one. You can't \"merge\"\n>> them.\n> \n> Ok, maybe CVS was not so good as an example of why versioned tags *are*\n> useful, but my comment came from the experience I have with the tagging\n> of FreeBSD release builds.  The -STABLE branch os FreeBSD may be tagged\n> with RELENG_X_Y_Z_RELEASE at a particular point in time.  If we find\n> that some important bug fix has to go in, the fix is committed, and the\n> tag can 'slide' forward for only a particular file or set of files.\n\nThat is a bad, bad idea. You should have v1.4.4 tag, and published tag\nshould be immutable, so if someone tells that there is bug in v1.4.4\nyou know what this version is. If you want to gather fixes for v1.4.4,\nyou make v1.4.4-fixes _branch_, commit fix on this branch (perhaps also\nmerging it into current work), and tag result v1.4.4.1 or v1.4.4-patch1.\nTags are meant to be immutable.\n\n> When tags are versioned, this operation is properly versioned too.  It's\n> apparent from browsing the global tag history that the specific tag\n> *was* moved forward; it's obvious where it was pointing before the\n> 'slide' operation; it's obvious which files the 'slide' affected, etc.\n\nThis operation IBHO has no sense; I understand that you can have local,\nprivate tags you slide like bisect-low, bisect-up, before-merge,...\nPublic tags: no.\n\n[...]\n>> In other words, tags are atomic *events*, not history. And I certainly\n>> agree that you shouldn't lose the events (unless you want to, of course).\n> \n> Tags are a little of two different things:\n> \n> (1) They are 'events' in the sense that someone has placed them to a\n> tree, and this operation is a very real, very natural event, and *this*\n> event should be versioned.\n\nTags should not be placed to a tree.\n\n[...]\n-- \nJakub Narebski\nPoland\n"}]}