|
I’ve just learned Git. What a wonderful system, thanks for building
it. And what an annoying learning experience. I promised myself to try to remember what made it all so hard, and to write it down in a comprehensive and possibly even constructive fashion. Here it is, for what it’s worth. Read it as the friendly, but somewhat exasparated suggestions of a newcomer. I’d love to help (in the form of submitting patches to the documentation or CLI responses), but I’d like to test the waters first. So, in no particular order, here are the highlights of my former confusion, if only for your entertainment. Comments are welcome, in particular where my suggestions are born out of ignorance. Remote (tracking) branches -------------------------- There are at least two uses of the word *tracking* in Git's terminology. The first, used in the form “git tracks a file” (in the sense that Git knows about the file) is harmless enough, and is handled under `git add` below. But the real monster is the *tracking branch*, sometimes called the remote branch, the remote-tracking branch, or the remote tracking branch. Boy did that ever confuse me. And, reading the git mailing list and the web, many others. There are so many things wrong with how this simple concept is obfuscated by the documentation that I have a hard time organising my thoughts about writing it down. Please, *please* fix this. It was the single most confusing and annoying part of learning Git. First, the word, “tracking”. These branches don’t track or follow anything. They are standing completely still. Please believe me that when first you are led to believe that origin/master tracks a branch on the remote (like a hound tracks it quarry, or a radar tracks a flight) that it is very difficult to hunt this misunderstanding down: I believed for a long time that the tracking branch stayed in sync, automagically, with a synonymous branch at the remote. The CLI and documentation worked very hard to keep me in that state of ignorance. I *know* that my colleague just updated the remote repository, yet the remote branch (or is the remote tracking branch? or the remote-tracking branch?) is as it always was...? (How could I *ever* believe that? Well, *now* I get it, and have a difficult time recollecting that misunderstanding. *Now* it’s easy.) Second, the word “remote” as opposed to “local”, a dichotomy enforced by both the documentation and by the output of `git branch -r` (list all remote branches, says user-manual.txt). Things began to dawn on me only when I understood that origin/master is certainly and absolutely a “local” branch, in the sense that it points to a commit in my local repository. (It differs from my other local branches mainly in how it is updated. It’s not committed to, but fetched to. But both are local, and the remote can be many commits ahead of me.) So, remote tracking branches are neither remote (they are *local* copies of how the remote once was) and they stand completely still until you tell them to “fetch”. So remote means local, and tracking means still, “local still-standing” would be a less confusing term that “remote tracking”. Lovely. Tracking branches *track* in the sense that a stuffed Basset Hound tracks. Namely, not. It‘s a dream of what once was. The hyphenated *remote-tracking* is a lot better terminology already (and sometimes even used in the documentation), because at least it doesn't pretend to be a remote branch (`git branch -r`, of course, still does). So that single hyphen already does some good, and should be edited for consistency. (It did take time for me to convince myself during the learning process that “remote tracking” and “remote-tracking” probably are the same thing, and “tracked remote” something else, abandoning and resurrecting these hypetheses several times.) And *even if* the word was meaningful and consistenly spelt, the documentation uses it to *refer* to different things. Assume that we have the branches master, origin/master, and origin’s master (understanding that they exist, and are different, is another Aha! moment largely prevented by the documentation). For 50 points, which is the remote tracking branch? Or the remote-tracking branch? The remote branch? Which branch tracks which other branch? Does master track anything? Nobody seems to know, and documentation and CLI include various inconsistent suggestions. (I know there have been long, and inconclusive threads about this on the git mailing list, and I learned a lot from seeing other people’s misconceptions mirror my own.) Granted, I think the term “tracked remote branch” is used with laudable consistentcy to refer to a branch on the remote. And “remote tracking branch” (with our without the hyphen) more often than not refers to origin/master. It may be that terminology is slowly converging. (To something confusing, but still...) But to appreciate how incredibly difficult this was to understand, check this, from the Git Community book: A 'tracking branch' in Git is a local branch that is connected to a remote branch. To a new user, who *almost* gets it, this is just a slap in the face. Which one of these is origin/master again? None? (Or rather, it is the confirmation one needs that nobody in the Git community cares much, so the once-believed-to-be-carefully-worded documentation loses some of its authority and therefore the learner can abandon some misunderstandings.) There probably is a radical case to be made for abandoning the word “tracking” entirely. First, because tracking branches don’t track, and second because “tracking” already means something else in Git (see below). I realise that this terminology is now so ingrained in Git users that conservatism will probably perpetuate it. But it would be *very* helpful to think this through, and at least agree on who “tracks” what. In the ideal world, origin/master would be something like “the fetching branch” for the origin’s master, or the “snapshot branch” or the “fetched branch”. (I am partial to use “fetching” because it makes that operation a first-class conceptual citizen, rather than pulling, which is another siren that lures newbies into a maelstroem of confusion.) More radically, I am sure some head scratching would be able to find useful terminology for master, origin/master, and origin’s master. I’d love to see suggestions. As I said, I admire how wonderfully simple and clean this has been implemented, and the documentation, CLI, and terminology should reflect that. The staging area ---------------- The wonderful and central concept of staging area exists under at least three names in Git terminology. And that’s really, really annoying. The index, the cache, and the staging area are all the same, which is a huge revelation to a newcomer. This problem could of course be easily fixed by making up your mind. The decision which of the three terms to adopt is somewhat arbitrary, but *staging area* gives the strongest and best metaphor. It also verb quite well, even though it is not the best, shortest noun. *Index* would have been a good word for the files known to Git (what is now called, sometimes, “tracked files”), and *cache* is terrible in any case. `git stage` is already part of the distribution. Great. 1. Search for index and cache in the documentation and rephrase any and all their occurences to use “staged” (or, if it can’t be avoided “the staging area”) instead. Say “staged to be committed” often, it’s a strong metaphor. 2. Introduce the alias `git unstage` for `git reset HEAD` in the standard distribution. 3. Duplicate various occurences of `cached` flags as `staged` (and change the documentation and man pages accordingly), so as to have, e.g., `git diff --staged`. git status ---------- One of the earliest-to-use commands is `git status`, whose message are *wordy*, but were initially completely unhelpful to me. In particular, working directory clean Clean? What’s this now? Clean and dirty are Git slang, and not what I want to meet as a new user. The message should inform me that the untracked files in the working directory are equal to their previous commit. But there are other things wrong with the message. For example, even though there’s nothing to commit: `nothing added to commit but untracked files present (use "git add" to track)`? The last paranethesis should set off warning bells already. And what did clean mean with respect to untracked files? And “added to commmit”? That sounds like amending. We add to the index or the staging area, don’t we, “ready to be included in the next commit,” so they aren’t added to that commit quite yet? changed but not updated: I’m still not sure what “update” was ever supposed to mean in this sentence. I just edited the file, so it’s updated, for crying out loud! The message might just say “Changed files, but not staged to be committed.” The meant-to-be helpful “use [...] to update what will be committed” is another can of worms, and I can find at least two ways to completely misunderstand this. Change to “use `git stage <file>` to stage”. (With the new command name it’s almost superfluous.) Here are some concrete suggestions: 1. nothing added to commit but untracked files present should be nothing staged to commit, but untracked files present (Comment: maybe “... but working directory contains untracked files.” I realise that “directory” is not quite comprehensive here, because files can reside in subdirectories. But I’d like to be more concrete than “be present”.) 2. Untracked files: (use "git add <file>..." to include in what will be committed) should be Untracked files: (use "git track <file>" to track) 3. Changes to be committed: (use "git reset HEAD <file>..." to unstage) should be Staged to be committed: (use "git unstage <file>" to unstage) Adding ------ The tutorial tells us that Many revision control systems provide an add command that tells the system to start tracking changes to a new file. Git's add command does something simpler and more powerful: git add is used both for new and newly modified files, and in both cases it takes a snapshot of the given files and stages that content in the index, ready for inclusion in the next commit. This is true, and once you grok how Git actually works it also makes complete sense. “Making the file known to Git” (sometimes called “tracking the file”) and “staging for the next commit” result in the exact same operations, from Git’s perspective. But this is a good example of what’s wrong with the way the documentation thinks: Git’s implementation perspective should not define how concepts are explained. In particular, *tracking* (in the sense of making a file known to git) and *staging* are conceptually different things. In fact, the two things remain conceptually different later on: un-tracking (removing the file from Git’s worldview) and un-staging are not the same thing at all, neither conceptually nor implementationally. The opposite of staging is `git reset HEAD <file>` and the opposite of tracking is -- well, I’m not sure, actually. Maybe `git update-index --force-remove <filename>`? But this only strenghtens my point: tracking and staging are different concepts, and therefore deserve different terms in the documentation and (ideally) in the CLI. The entire quoted paragraph in the tutorial can be removed: there’s simply no reason to tell the reader that git behaves differently from other version control systems (indeed, to take some perverse *pride* in that fact). Fixing this requires no change to the implementation. `git stage` is already a synonym for `git add`. It merely requires discipline in using the terminology of staging. Note that it completely valid to tell the reader, maybe immediately and in a footnote, that `git add` and `git stage` *are* indeed synonyms, because of Git’s elegant model. In fact, given the amount of documentation cruft one can find on the Internet, this would be a welcome footnote. An even more radical suggestion (which would take all of 20 seconds to implement) is to introduce `git track` as another alias for `git add`. (See above under `git status`). This would be especially useful if tracking *branches* no longer existed. There’s another issue with this, namely that “added files are immediately staged”. In fact, I do understand why Git does that, but conceptually it’s pure evil: one of the conceptual conrnerstones of Git -- that files can be tracked and changed yet not staged, i.e., the staging areas is conceptually a first-class citizen -- is violated every time a new file is “born”. Newborn files are *special* until their first commit, and that’s a shame, because the first thing the new file (and, vicariously, the new user) experiences is an aberration. I admit that I have not thought this through.-- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
Hi Thore,
Thore Husfeldt wrote: > what an annoying learning experience. > > I promised myself to try to remember what made it all so hard, and to > write it down in a comprehensive and possibly even constructive > fashion. Thanks for doing this work! > There probably is a radical case to be made for abandoning the word > “tracking” entirely. First, because tracking branches don’t track, and > second because “tracking” already means something else in Git (see > below). I think you are overthinking this "tracking like a Basset hound" thing. When a person keeps a diary to track their appointments, is it always up to date? No, it is only as up to date as the person is diligent. Similarly, git provides a namespace for branches that a person can use to track remote branches, which is only as up to date as one keeps it. So what would be a better term? > In the ideal world, origin/master would be something > like “the fetching branch” for the origin’s master, or the “snapshot > branch” or the “fetched branch”. Familiarity might be leaving me blind, but these all sound even more confusing to me. In fact, origin/master is not only updated by fetching but by pushing (at least if I remember correctly). It is meant to be git's local memory of remote content. Using the term "remote-tracking" consistently would certainly be an improvement and would make it easier to do a search-and-destroy (erm, -and-replace) if another term comes up that seems to fit the concept better. > The wonderful and central concept of staging area exists under at > least three names in Git terminology. And that’s really, really > annoying. The index, the cache, and the staging area are all the same, > which is a huge revelation to a newcomer. Heh. Personally I tend to think in terms of "the index". e.g., "git add" registers changes for use in the next commit. Information about the commit in preparation is stored in the index. Why? Because "staging area" has this misleading feeling of not-jargon. It is jargon and when misused can be very confusing (to me, at least). > 2. Introduce the alias `git unstage` for `git reset HEAD` in the > standard distribution. Doesn't "git reset" ('reset the staged content to match...') fit the same metaphor? > 3. Duplicate various occurences of `cached` flags as `staged` (and > change the documentation and man pages accordingly), so as to have, > e.g., `git diff --staged`. Already exists (though in practice it tends to be easier to teach --cached since that is the option that documents all over the web use). > Clean? What’s this now? Clean and dirty are Git slang, and not what I > want to meet as a new user. The message should inform me that the > untracked files in the working directory are equal to their previous > commit. Huh? Anyway, improvements welcome (in the form of a simple mockup, or even better, patches). > changed but not updated: > > I’m still not sure what “update” was ever supposed to mean in this > sentence. It's historical residue. (What is now done with "git add" used to be done with "git update-index"). > Untracked files: > (use "git add <file>..." to include in what will be committed) > > should be > > Untracked files: > (use "git track <file>" to track) Is this "git track" a synonym for "git add -N"? > The opposite of staging is `git > reset HEAD <file>` and the opposite of tracking is -- well, I’m not > sure, actually. Ah, this is a kind of obnoxious thing! For a newly added file, git reset -- <path> ought to un-add it, but it doesn't. For a file that has been around for a while, removal is imho just adding a different kind of change. It would be nice if git add -- <path> pointed to "git rm --cached" to help the operator to do that. > The entire quoted paragraph in the tutorial can be removed: there’s > simply no reason to tell the reader that git behaves differently from > other version control systems How will a person used to e.g. cvs ever adjust if they don't even realize git is different? Hope that helps, Jonathan -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Thore Husfeldt
Heya,
[+Scott, who's done a lot of work on making git more newbie friendly] [+Jonathan, I saw his reply just before sending this] On Mon, Oct 18, 2010 at 15:45, Thore Husfeldt <[hidden email]> wrote: > I’ve just learned Git. What a wonderful system, thanks for building > it. Thanks. > And what an annoying learning experience. Thanks again :). > I promised myself to try to remember what made it all so hard, and to > write it down in a comprehensive and possibly even constructive > fashion. Here it is, for what it’s worth. Read it as the friendly, but > somewhat exasperated suggestions of a newcomer. I’d love to help (in > the form of submitting patches to the documentation or CLI responses), > but I’d like to test the waters first. Awesome! Your experiences are very welcome indeed! > So, remote tracking branches are neither remote (they are *local* > copies of how the remote once was) and they stand completely still > until you tell them to “fetch”. So remote means local, and tracking > means still, “local still-standing” would be a less confusing term > that “remote tracking”. Lovely. *chortles*, nicely observed. > The hyphenated *remote-tracking* is a lot better terminology already > (and sometimes even used in the documentation), because at least it > doesn't pretend to be a remote branch (`git branch -r`, of course, > still does). What do you mean with the last part (about `git branch -r`)? The fact that 'refs/remotes' is not immutable? > So that single hyphen already does some good, and should > be edited for consistency. If we agree that "remote-tracking" is the way to go, a patch doing such editing would be very welcome. > And *even if* the word was meaningful and consistently spelt, the > documentation uses it to *refer* to different things. Assume that we > have the branches master, origin/master, and origin’s master > (understanding that they exist, and are different, is another Aha! > moment largely prevented by the documentation). How could the documentation make this more clear? > Or rather, it is the confirmation one needs that nobody in the Git > community cares much On the contrary, we care a lot, but once you're not a new user yourself anymore, it's hard to know what to fix. > There probably is a radical case to be made for abandoning the word > “tracking” entirely. First, because tracking branches don’t track, and > second because “tracking” already means something else in Git (see > below). I realise that this terminology is now so ingrained in Git > users that conservatism will probably perpetuate it. But it would be > *very* helpful to think this through, and at least agree on who > “tracks” what. In the ideal world, origin/master would be something > like “the fetching branch” for the origin’s master, or the “snapshot > branch” or the “fetched branch”. > [...] > More radically, I am sure some head scratching would be able to find > useful terminology for master, origin/master, and origin’s master. I’d > love to see suggestions. As I said, I admire how wonderfully simple > and clean this has been implemented, and the documentation, CLI, and > terminology should reflect that. I don't have any objections to changing these terms, but I don't have any suggestions on what to change them _to_. > 2. Introduce the alias `git unstage` for `git reset HEAD` in the > standard distribution. (or 'git rm --cached' for newly added files) > nothing added to commit but untracked files present > > should be > > nothing staged to commit, but untracked files present I've always liked the whole 'stage(d)' concept, so I like this, but I remember Junio being fairly hesitant to use it more extensively. > (Comment: maybe “... but working directory contains untracked files.” > I realise that “directory” is not quite comprehensive here, because > files can reside in subdirectories. We use "worktree" elsewhere, how about that? > (use "git track <file>" to track) So basically you want to split out 'git add' into 'git track' and 'git stage'? > Changes to be committed: > (use "git reset HEAD <file>..." to unstage) > > should be > > Staged to be committed: > (use "git unstage <file>" to unstage) This would be extra nice since 'git unstage' could also be used in a fresh repository. > But this is a good example of what’s wrong with the way the > documentation thinks: Git’s implementation perspective should not > define how concepts are explained. In particular, *tracking* (in the > sense of making a file known to git) and *staging* are conceptually > different things. In fact, the two things remain conceptually > different later on: un-tracking (removing the file from Git’s > worldview) and un-staging are not the same thing at all, neither > conceptually nor implementationally. Fair point, I think. > The opposite of staging is `git > reset HEAD <file>` and the opposite of tracking is -- well, I’m not > sure, actually. Maybe `git update-index --force-remove <filename>`? 'git rm --cached' > The entire quoted paragraph in the tutorial can be removed: there’s > simply no reason to tell the reader that git behaves differently from > other version control systems I disagree, many people come from another VCS, and pointing out where their assumptions are invalid is generally useful. > There’s another issue with this, namely that “added files are > immediately staged”. In fact, I do understand why Git does that, but > conceptually it’s pure evil: one of the conceptual conrnerstones of > Git -- that files can be tracked and changed yet not staged, i.e., the > staging areas is conceptually a first-class citizen -- is violated > every time a new file is “born”. Newborn files are *special* until > their first commit, and that’s a shame, because the first thing the > new file (and, vicariously, the new user) experiences is an > aberration. Eh, I think it's not an aberration, it's more of a convenience. I don't think the benefit of making the concept of tracking vs. staging clear to the user is worth the hassle of having to execute two things to do one thing (staging a new file). You can also see it the other way around, why are new files any different from other files? Why shouldn't you be able to stage new files? -- Cheers, Sverre Rabbelier -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Thore Husfeldt
Thore Husfeldt <[hidden email]> writes:
> Read it as the friendly, but > somewhat exasparated suggestions of a newcomer. I’d love to help (in > the form of submitting patches to the documentation or CLI responses), > but I’d like to test the waters first. (it's common practice here to test the water with RFC/PATCHes too) > There are at least two uses of the word *tracking* in Git's > terminology. Actually, there's a third, known to be rather unfortunate. For example, when you clone a repository, by default, you end up with 1) The master branch hosted remotely 2) origin/master, locally, but "remote-tracking" 3) master, your working branch. When you do a "git pull" when sitting on local branch master, Git knows it must : a) fetch (i.e. download) from branch 1) into branch 2) b) merge from branch 2) into branch 1) Rule a) come from remote.<remotename>.fetch, and rule b) comes from branch.master.merge in your .git/config. Usually, we refer to tracking branch to mean rule a), but the "track" in "git branch --track" means "setup git for rule b) above". We already came up with a better wording, namely "upstream", and used in in "git push --set-upstream". Probably a next step would be to deprecate any other occurence of --track meaning the same thing (git checkout --track seems to me to be a candidate, git branch has both --track and --set-upstream). One difficulty is to do that with backward compatibility in mind. > 3. Duplicate various occurences of `cached` flags as `staged` (and > change the documentation and man pages accordingly), so as to have, > e.g., `git diff --staged`. I do like this, but to be complete, one should also deal with more complex cases. For example, "git apply" has _both_ --index and --cached, with different semantics. And changing just _some_ of the occurences of --index and --cached may help, but do not fix the problem of inconsistancies. Up to now, there have been many efforts towards consistancy, but I guess no one had the courrage of doing a global-enough approach to eliminate all inconsistancies. In other words, I encourage you to continue the effort you've stated here, but that won't help much unless you push the idea far enough IMHO. > changed but not updated: > > I’m still not sure what “update” was ever supposed to mean in this > sentence. Historically, the staging area was seen as a cache (hence the name), which was purposedly out-of-date when doing a partial commit. Hence, Git inherited some of the terminology of usual caches (a cache is "dirty" when it's not in sync with what it caches, "clean" when it is, and you "update" it to make it in sync). But I do agree that the analogy with a cache is disturbing for the user, even if it's meaningful for the developper: as a user, a cache is meant to be a performance optimization, not supposed to interfer with the functionality. > 2. > Untracked files: > (use "git add <file>..." to include in what will be committed) > > should be > > Untracked files: > (use "git track <file>" to track) This hypothetical "git track" actually exists under the name "git add -N". > The opposite of staging is `git > reset HEAD <file>` and the opposite of tracking is -- well, I’m not > sure, actually. Maybe `git update-index --force-remove <filename>`? git rm --cached ? As a bare mortal, you shouldn't need update-index, it's a plumbing command (i.e. meant for scripts or low-level manipulations). > An even more radical suggestion (which would take all of 20 seconds to > implement) is to introduce `git track` as another alias for `git > add`. (See above under `git status`). This would be especially useful > if tracking *branches* no longer existed. I disagree that adding aliases would help users. See your confusion, and then the relief when you found out that index, cache, and staging area were synonymous. Now, what should a user think after learning stage, track and add, and asking for the difference. I agree that adding new files and adding new content to existing files are done for different reasons, but the conceptual simplicity of Git comes from the fact that Git is purely snapshot oriented, and I to some extent, it's nice to have this reflected in the user-interface. When you say "git add X", you don't talk about the difference between the previous commit and the next, or about the difference between working tree and next commit, or so. You're basically saying "file X will exist in the next commit, and it will have this content". Whether it existed or not in the previous commit doesn't matter. It's implemented this way, and it's really something fundamental in the Git model. > There’s another issue with this, namely that “added files are > immediately staged”. In fact, I do understand why Git does that, but > conceptually it’s pure evil: one of the conceptual conrnerstones of > Git -- that files can be tracked and changed yet not staged, Rephrase that as "the working tree can have content different from the staged content". Both "working tree content" and "staged content" are snapshot (i.e. they exist regardless of each other). Then newly created files won't be different anymore. Files exist, with some (possibly empty) content, or they don't. -- Matthieu Moy http://www-verimag.imag.fr/~moy/ -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Thore Husfeldt
Thore Husfeldt <[hidden email]> writes:
> Ive just learned Git. What a wonderful system, thanks for building > it. > > And what an annoying learning experience. > > I promised myself to try to remember what made it all so hard, and to > write it down in a comprehensive and possibly even constructive > fashion. Here it is, for what its worth. Read it as the friendly, but > somewhat exasparated suggestions of a newcomer. Id love to help (in > the form of submitting patches to the documentation or CLI responses), > but Id like to test the waters first. Thank you very much for writing those down. It is very helpful for us, which are used to Git and know by heart its sometimes obscure jargon, and might not notice that it is hard to understand. > Remote (tracking) branches > -------------------------- > > There are at least two uses of the word *tracking* in Git's > terminology. > > The first, used in the form `git tracks a file' (in the sense that Git > knows about the file) is harmless enough, and is handled under `git > add` below. In this sense of "tracked", i.e. "tracked file", it means that given file is versioned / is under version control. Though I don't think we use `git tracks a file` anywhere in the documentation and messages (at least I hope so); we use `tracked file`. I think it is all right for `tracked file` and `"tracked" branch` to mean different things. > But the real monster is the *tracking branch*, sometimes called the > remote branch, the remote-tracking branch, or the remote tracking > branch. Boy did that ever confuse me. [...] > > Please, *please* fix this. It was the single most confusing and > annoying part of learning Git. > > First, the word, "tracking". These branches dont track or follow > anything. They are standing completely still. Please believe me that > when first you are led to believe that origin/master tracks a branch > on the remote (like a hound tracks it quarry, or a radar tracks a > flight) that it is very difficult to hunt this misunderstanding down: > I believed for a long time that the tracking branch stayed in sync, > automagically, with a synonymous branch at the remote. But those 'remote-tracking branches' are *used* to track where there are branches in remote repository. Sidenote: give thanks that you didn't start to use git before version 1.5.0, when so called "separate remote" layout was made default (which means tracking branch 'foo' in remote 'origin' using 'origin/foo' remote-tracking branch). [...] > The hyphenated *remote-tracking* is a lot better terminology already > (and sometimes even used in the documentation), because at least it > doesn't pretend to be a remote branch (`git branch -r`, of course, > still does). So that single hyphen already does some good, and should > be edited for consistency. [...] The name 'remote-tracking branch' is the name we arrived at after long discussions not that long time ago, and it is a name that should be used thorough the documentation. It is ongoing effort. > [...] It may be that terminology is slowly converging. (To something > confusing, but still...) [...] > More radically, I am sure some head scratching would be able to find > useful terminology for master, origin/master, and origins master. Id > love to see suggestions. As I said, I admire how wonderfully simple > and clean this has been implemented, and the documentation, CLI, and > terminology should reflect that. There is also additional complication that you can have the same relation that local branch 'master' has to 'origin/master' remote-tracking branch with two local branches. We nowadays say that 'origin/master' is "upstream" for 'master' branch; we used to say that 'master' branch "tracks" 'origin/master' branch (which can be seen in the name of `--track' option to 'git branch'). > The staging area > ---------------- > > The wonderful and central concept of staging area exists under at > least three names in Git terminology. And thats really, really > annoying. The index, the cache, and the staging area are all the same, > which is a huge revelation to a newcomer. This inconsistence is results of historical issues; the concrete object that is used as mediator betweeb working area and repository was first called 'dircache', and now is called 'the index'. There was strong push towards replacing 'index' and 'cache' by 'staging area' (and 'to stage' as verb), but it meets with some resistance. > 2. Introduce the alias `git unstage` for `git reset HEAD` in the > standard distribution. That is IMHO a very good idea. The `git unstage <file>` form describes what we want to achieve (user story), while `git reset HEAD <file>` requires us to know what operation must we do in order to remove staged changes from a file. > 3. Duplicate various occurences of `cached` flags as `staged` (and > change the documentation and man pages accordingly), so as to have, > e.g., `git diff --staged`. Note that it is not as easy as it seems at first glance. There are *two* such options, which (as you can read in gitcli(7) manpage) have slightly different meaning: * The `--cached` option is used to ask a command that usually works on files in the working tree to *only* work with the index. For example, `git grep`, when used without a commit to specify from which commit to look for strings in, usually works on files in the working tree, but with the `--cached` option, it looks for strings in the index. * The `--index` option is used to ask a command that usually works on files in the working tree to *also* affect the index. For example, `git stash apply` usually merges changes recorded in a stash to the working tree, but with the `--index` option, it also merges changes to the index as well. Some commands like `git apply` support both (though not at the same time). > git status > ---------- [...] > 2. > Untracked files: > (use "git add <file>..." to include in what will be committed) > > should be > > Untracked files: > (use "git track <file>" to track) To "track a file" means to put a file under version control (to version control the file). Note also that "git track <file>" would be "git add -N <file>" (where `-N` is `--intent-to-add`), which only marks a file to be tracked / versioned, but doesn't stage its contents. > Adding > ------ > > The tutorial tells us that > > Many revision control systems provide an add command that tells > the system to start tracking changes to a new file. Git's add > command does something simpler and more powerful: git add is used > both for new and newly modified files, and in both cases it takes > a snapshot of the given files and stages that content in the > index, ready for inclusion in the next commit. > > This is true, and once you grok how Git actually works it also makes > complete sense. `Making the file known to Git' (sometimes called > `tracking the file') and `staging for the next commit' result in the > exact same operations, from Gits perspective. > > But this is a good example of whats wrong with the way the > documentation thinks: Gits implementation perspective should not > define how concepts are explained. In particular, *tracking* (in the > sense of making a file known to git) and *staging* are conceptually > different things. But they are not independent. When you stage contents of a file which was not known to git, it is automatically made "tracked" i.e. put under version control. Obvious. > In fact, the two things remain conceptually > different later on: un-tracking (removing the file from Gits > worldview) and un-staging are not the same thing at all, neither > conceptually nor implementationally. The opposite of staging is `git > reset HEAD <file>` and the opposite of tracking is -- well, Im not > sure, actually. Maybe `git update-index --force-remove <filename>`? `git rm <filename>` to remove it both from staging area, and working area, or `git rm --cached <filename>` to remove it only from staging area, which means that it is removed from version control but kept on disk. [...] > Fixing this requires no change to the implementation. `git stage` is > already a synonym for `git add`. It merely requires discipline in > using the terminology of staging. Note that it completely valid to > tell the reader, maybe immediately and in a footnote, that `git add` > and `git stage` *are* indeed synonyms, because of Gits elegant > model. In fact, given the amount of documentation cruft one can find > on the Internet, this would be a welcome footnote. > > An even more radical suggestion (which would take all of 20 seconds to > implement) is to introduce `git track` as another alias for `git > add`. (See above under `git status`). This would be especially useful > if tracking *branches* no longer existed. Well, there is different suggestion: make `git stage`, `git track` and `git mark-resolved` to be *specializations* of `git add`, with added safety checks: 'git stage' would work only on files known to git / under version control already, 'git track' would work only on untracked files (and do what 'git add -N' does), and 'git mark-resolved' would work only on files which were part of a merge conflict. > Theres another issue with this, namely that added files are > immediately staged. In fact, I do understand why Git does that, but > conceptually its pure evil: one of the conceptual conrnerstones of > Git -- that files can be tracked and changed yet not staged, i.e., the > staging areas is conceptually a first-class citizen -- is violated > every time a new file is born. Newborn files are *special* until > their first commit, and thats a shame, because the first thing the > new file (and, vicariously, the new user) experiences is an > aberration. I admit that I have not thought this through. -- Jakub Narebski Poland ShadeHawk on #git -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Jonathan Nieder-2
Suppose I try to use "git reset" to un-add an new, unwanted file:
echo hello >foo.c git add foo.c rm foo.c; # bad file! bad! git reset foo.c The file foo.c does not exist on disk, so "git reset" rejects the request with fatal: ambiguous argument 'foo.c': unknown revision or path not in the working tree. Use '--' to separate paths from revisions Git can do better: since foo.c is not a revision and has an entry in the index, it is clear the request refers to a path and not a rev. Signed-off-by: Jonathan Nieder <[hidden email]> --- Jonathan Nieder wrote: > Ah, this is a kind of obnoxious thing! For a newly added file, > > git reset -- <path> > > ought to un-add it, but it doesn't. Err, yes it does. Probably I was thinking of rm <path> git reset <path> producing an "ambiguous argument" message. builtin/reset.c | 8 +++++++- t/t7102-reset.sh | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/builtin/reset.c b/builtin/reset.c index 0037be4..7d23d75 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -295,7 +295,13 @@ int cmd_reset(int argc, const char **argv, const char *prefix) rev = argv[i++]; } else { /* Otherwise we treat this as a filename */ - verify_filename(prefix, argv[i]); + const char *name = argv[i]; + if (prefix) + name = prefix_filename(prefix, strlen(prefix), name); + if (read_cache() < 0) + die("Could not read index"); + if (cache_name_pos(name, strlen(name)) < 0) + verify_filename(prefix, argv[i]); } } diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index b8cf260..69d125e 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -5,7 +5,7 @@ test_description='git reset -Documented tests for git reset' +Miscellaneous tests for git reset' . ./test-lib.sh @@ -441,6 +441,15 @@ test_expect_success 'disambiguation (1)' ' ' +test_expect_success "disambiguation (1')" ' + + git reset --hard && + git reset secondfile && + git diff --exit-code && + git diff --cached --exit-code + +' + test_expect_success 'disambiguation (2)' ' git reset --hard && @@ -448,11 +457,18 @@ test_expect_success 'disambiguation (2)' ' git add secondfile && rm -f secondfile && test_must_fail git reset secondfile && - test -n "$(git diff --cached --name-only -- secondfile)" && + test -z "$(git diff --cached --name-only)" && test ! -f secondfile ' +test_expect_success "disambiguation (2')" ' + + git reset --hard && + test_must_fail git reset doesnotexist + +' + test_expect_success 'disambiguation (3)' ' git reset --hard && @@ -465,6 +481,13 @@ test_expect_success 'disambiguation (3)' ' ' +test_expect_success "disambiguation (3')" ' + + git reset --hard && + git reset HEAD doesnotexist + +' + test_expect_success 'disambiguation (4)' ' git reset --hard && @@ -476,4 +499,11 @@ test_expect_success 'disambiguation (4)' ' test ! -f secondfile ' +test_expect_success "disambiguation (4')" ' + + git reset --hard && + git reset -- doesnotexist + +' + test_done -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
Jonathan Nieder <[hidden email]> writes:
> Suppose I try to use "git reset" to un-add an new, unwanted file: > > echo hello >foo.c > git add foo.c > rm foo.c; # bad file! bad! > git reset foo.c > > The file foo.c does not exist on disk, so "git reset" rejects the > request with > > fatal: ambiguous argument 'foo.c': unknown revision or path not in the working tree. > Use '--' to separate paths from revisions > > Git can do better: since foo.c is not a revision and has an entry in > the index, it is clear the request refers to a path and not a rev. > > Signed-off-by: Jonathan Nieder <[hidden email]> > --- This changes the definition of path/rev disambiguation only for "reset" and makes things inconsistent. Is it a good thing? If a token is not a filename in the working tree, but is a path in the index, and at the same time is a valid ref, wouldn't it make the token ambiguous with the updated definition of disambiguation code here? > diff --git a/builtin/reset.c b/builtin/reset.c > index 0037be4..7d23d75 100644 > --- a/builtin/reset.c > +++ b/builtin/reset.c > @@ -295,7 +295,13 @@ int cmd_reset(int argc, const char **argv, const char *prefix) > rev = argv[i++]; > } else { > /* Otherwise we treat this as a filename */ > - verify_filename(prefix, argv[i]); > + const char *name = argv[i]; > + if (prefix) > + name = prefix_filename(prefix, strlen(prefix), name); > + if (read_cache() < 0) > + die("Could not read index"); > + if (cache_name_pos(name, strlen(name)) < 0) > + verify_filename(prefix, argv[i]); > } > } Makes me wonder - if we can/want to have a logic like this inside verify_filename(); - if we need a corresponding logic in either the previous else/if cascade that calls verify_non_filename(), or in verify_non_filename() itself. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Sverre Rabbelier-2
Sverre Rabbelier <[hidden email]> writes:
>> More radically, I am sure some head scratching would be able to find >> useful terminology for master, origin/master, and origin’s master. I’d >> love to see suggestions. As I said, I admire how wonderfully simple >> and clean this has been implemented, and the documentation, CLI, and >> terminology should reflect that. > > I don't have any objections to changing these terms, but I don't have > any suggestions on what to change them _to_. I do not think debating on changing the terminology is a particularly productive use of our time. Just like Thore was confused by "index, cache, add, stage", we would end up adding yet another lingo that cover the same concept, and the problem is that there is _no way_ older words will be forgotten. But I think the way the concepts are explained and taught by our documentation can and should be improved. For example, as I've written before we use 'tracking' for two quite different purposes, which is a mistake and the source confusion. - A "remote-tracking branch" is "a _thing_ whose purpose is to be used to track a branch on the remote side", and "fetch" is how you update it. - Sometimes people call a local branch whose purpose is to be used to build on efforts made on a branch on a remote repository as "tracking", which is quite incompatible with the above one. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Junio C Hamano
Junio C Hamano wrote:
> Makes me wonder > > - if we can/want to have a logic like this inside verify_filename(); Yes, I think so. I was worried that this would be confusing for some command that looks to the worktree, like git grep without --cached, but I suspect that worry was unfounded. The one case I am worried about is "git rev-parse". What is "git rev-parse <path>" supposed to be used for? > - if we need a corresponding logic in either the previous else/if cascade > that calls verify_non_filename(), or in verify_non_filename() itself. Yes. Is it safe to load the index so early? I can imagine a person trying "git reset" to recover from a corrupted index; are we regressing in that respect and how would one check for it? -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Matthieu Moy-2
Matthieu Moy <[hidden email]> writes:
> We already came up with a better wording, namely "upstream", and used > in in "git push --set-upstream". Probably a next step would be to > deprecate any other occurence of --track meaning the same thing That doesn't make much sense to me; "upstream" and "track" are not alternatives; rather, they're complementary: "upstream" is a _thing_, and "track" is an _action_ -- one _tracks_ _upstream_. "--track", then, merely implies "upstream", which seems fine to me, as I'm not sure there's anything else it could refer to. I think the original post, while well-meaning is a bit overwrought, and reflects the difficulty in learning any new system as much as it does any inconsistency in git's terminology[*] -- Git's huge sin, after all (judging from most complaints I see about it), is that It Doesn't Use Exactly The Same Model (and thus Terminology) That CVS Did... [SVN's great sin, of course, is that It Does (interpret "CVS" liberally here).] [*] Git is certainly guilty of using inconsistent terminology -- cached/staged/index/yada is my personal complaint -- but I don't think to anywhere near the degree implied by that post. -Miles -- Do not taunt Happy Fun Ball. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
El 19/10/2010, a las 06:49, Miles Bader escribió:
> I think the original post, while well-meaning is a bit overwrought, and > reflects the difficulty in learning any new system as much as it does > any inconsistency in git's terminology[*] -- Git's huge sin, after all > (judging from most complaints I see about it), is that It Doesn't Use > Exactly The Same Model (and thus Terminology) That CVS Did... I don't think it's overwrought at all. It's just pointing out a couple of obvious road-bumps in the learning curve. We should smooth out these road-bumps (in so far as we can, with respect to backward compatibility and such) rather than just hand-waving them away saying that they are a natural consequence of demolishing the CVS world view and replacing it with something better. That's not true at all; mistakes _were_ made with the terminology, and unfortunately we have to live with some of them because they can't be changed in a non-breaking way, but the changes that we _can_ make to remove the confusion, we should make them. Cheers, Wincent -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
On Tue, Oct 19, 2010 at 4:19 PM, Wincent Colaiuta <[hidden email]> wrote:
> We should smooth out these road-bumps (in so far as we can, with respect to backward compatibility and such) rather than just hand-waving them away saying that they are a natural consequence of demolishing the CVS world view and replacing it with something better. That's not true at all; mistakes _were_ made with the terminology, and unfortunately we have to live with some of them because they can't be changed in a non-breaking way, but the changes that we _can_ make to remove the confusion, we should make them. Sure, I'm not claiming that git's perfect or can't be improved. [As I noted, I have my own list of complaints about its terminology.] However, just as it's wrong to ignore all complaints for such reasons, it's _equally_ wrong to assume the opposite and think that all such complaints are justified. Some differences in terminology _are_ due to a very different model, and can't simply be papered over. It isn't "hand-waving" to point this out. They might (and should) be better documented/explained, but there are definitely terms and concepts where the only reasonable solution is for newbies to have some patience and take some time to learn them. My impression of the original post was that it contained a little of both. -Miles -- Cat is power. Cat is peace. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
El 19/10/2010, a las 09:48, Miles Bader escribió:
> On Tue, Oct 19, 2010 at 4:19 PM, Wincent Colaiuta <[hidden email]> wrote: >> We should smooth out these road-bumps (in so far as we can, with respect to backward compatibility and such) rather than just hand-waving them away saying that they are a natural consequence of demolishing the CVS world view and replacing it with something better. That's not true at all; mistakes _were_ made with the terminology, and unfortunately we have to live with some of them because they can't be changed in a non-breaking way, but the changes that we _can_ make to remove the confusion, we should make them. > > Sure, I'm not claiming that git's perfect or can't be improved. [As I > noted, I have my own list of complaints about its terminology.] > > However, just as it's wrong to ignore all complaints for such reasons, > it's _equally_ wrong to assume the opposite and think that all such > complaints are justified. Some differences in terminology _are_ due > to a very different model, and can't simply be papered over. It isn't > "hand-waving" to point this out. They might (and should) be better > documented/explained, but there are definitely terms and concepts > where the only reasonable solution is for newbies to have some > patience and take some time to learn them. Well, I'm not "assuming" that the complaints are justified; I'm talking from 3.5 years of personal experience using Git: - the concept of the "index": learnt it in 30 seconds, and sick of hearing people complain about it - terminology related to concepts of "tracking"/"remote(s)": discomfort almost every time I've had to deal with it gitglossary(7) helps, but no matter how good it is you'll still get confusion unless the terminology is used consistently across the board. Some of this is not actually Git's fault, as a lot of the misuse/abuse of terminology actually comes from people writing blog posts and presentations and not being disciplined about their use of language -- before you know it Google returns mostly garbage results and "the community" ends up speaking a corrupted version of the language -- but the stuff that is within the scope of the Git project itself (man pages, official docs, interfaces) really needs to be top notch. Cheers, Wincent -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Jakub Narębski
> * The `--cached` option is used to ask a command that
Doesn't this just offer opportunity for two new options? E.g., --staged
> usually works on files in the working tree to *only* work > with the index. For example, `git grep`, when used > without a commit to specify from which commit to look for > strings in, usually works on files in the working tree, > but with the `--cached` option, it looks for strings in > the index. > > * The `--index` option is used to ask a command that > usually works on files in the working tree to *also* > affect the index. For example, `git stash apply` usually > merges changes recorded in a stash to the working tree, > but with the `--index` option, it also merges changes to > the index as well. and --also-staged or --include-staged or something? In the current form, these two options provide a variation of the same concept, using completely different option names (which could lead people to think that they're really the same option, just inconsistently implemented). So, regardless of changing over to --staged, I guess these two options could be made more consistent (though sticking to the "index" terminology is tricky, since that would require --cached to be become --index and --index to become --include--index, which throws away backward compatibility...). FWIW, I do rather like the "staging area" concept, since I feel it accurately describes its use (or at least the most common use of the staging area). Gr. Matthijs |
|
On Tue, 19 Oct 2010, Matthijs Kooijman wrote:
Note that the excerpt cited (quoted) below is directly from gitcli(7) manpage. > > * The `--cached` option is used to ask a command that > > usually works on files in the working tree to *only* work > > with the index. For example, `git grep`, when used > > without a commit to specify from which commit to look for > > strings in, usually works on files in the working tree, > > but with the `--cached` option, it looks for strings in > > the index. Mnemonic: operate on _cached_ contents. We could use `--staged` instead of `--cached` here, but for me it doesn't as strong as `--cached` this meaning. > > > > * The `--index` option is used to ask a command that > > usually works on files in the working tree to *also* > > affect the index. For example, `git stash apply` usually > > merges changes recorded in a stash to the working tree, > > but with the `--index` option, it also merges changes to > > the index as well. Mnemonic: include _index_ (the name for concrete implementation of the staging area) in operation. We could use `--stage` here, but it would be confusingly similar to `--staged`. We could use `--include-staged` or `--also-staged`, but it is long and unwieldy, and doesn't read as nice. > > Doesn't this just offer opportunity for two new options? E.g., --staged > and --also-staged or --include-staged or something? In the current form, > these two options provide a variation of the same concept, using > completely different option names (which could lead people to think > that they're really the same option, just inconsistently implemented). That's why documentation is for. That is why we have gitcli(7). Sidenote: there were some proposal of including pseudo-ref name for cache/index/staging area (and for workdir contents), i.e. to use for example INDEX or STAGE instead of `--cached`... but they fell flat because `--cached` / STAGE is not exactly like the ref, and it felt like it would contribute to confusion rather than reducing it. > > So, regardless of changing over to --staged, I guess these two options > could be made more consistent (though sticking to the "index" > terminology is tricky, since that would require --cached to be become > --index and --index to become --include-index, which throws away > backward compatibility...). Breaking backward compatibility that badly is a big NO. Unfortunately the need for backward compatibility prevents us from some of improvements... > > FWIW, I do rather like the "staging area" concept, since I feel it > accurately describes its use (or at least the most common use of the > staging area). I also like "staging area" concept (and "to stage" as a verb), but there are some difficulties in applying it thorough and through. -- Jakub Narebski Poland -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Thore Husfeldt
Although Git interally has the facility to differentiate between
porcelain and plubmbing commands and appropriately print errors, several shell scripts invoke plubming commands triggering cryptic plumbing errors to be displayed on a porcelain interface. This patch replaces the "needs update" message in git-pull and git-rebase, when `git update-index` is run, with a more friendly message. Reported-by: Joshua Jensen <[hidden email]> Reported-by: Thore Husfeldt <[hidden email]> Signed-off-by: Ramkumar Ramachandra <[hidden email]> --- Ref: <[hidden email]> for v2. Ref: <[hidden email]> for v1. Thanks to Matthieu for reviewing v1 and Junio for reviewing v2: I've tried to attack the problem more conservatively in this patch. It doesn't list paths, and doesn't print "generic" advice. git-pull.sh | 5 +---- git-rebase--interactive.sh | 14 +++----------- git-rebase.sh | 14 +------------- git-sh-setup.sh | 29 +++++++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/git-pull.sh b/git-pull.sh index 8eb74d4..20a3bbe 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -201,10 +201,7 @@ test true = "$rebase" && { die "updating an unborn branch with changes added to the index" fi else - git update-index --ignore-submodules --refresh && - git diff-files --ignore-submodules --quiet && - git diff-index --ignore-submodules --cached --quiet HEAD -- || - die "refusing to pull with rebase: your working tree is not up-to-date" + require_clean_work_tree "pull with rebase" "Please commit or stash them." fi oldremoteref= && . git-parse-remote && diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index a27952d..4d8a2a0 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -153,14 +153,6 @@ run_pre_rebase_hook () { fi } -require_clean_work_tree () { - # test if working tree is dirty - git rev-parse --verify HEAD > /dev/null && - git update-index --ignore-submodules --refresh && - git diff-files --quiet --ignore-submodules && - git diff-index --cached --quiet HEAD --ignore-submodules -- || - die "Working tree is dirty" -} ORIG_REFLOG_ACTION="$GIT_REFLOG_ACTION" @@ -557,7 +549,7 @@ do_next () { exit "$status" fi # Run in subshell because require_clean_work_tree can die. - if ! (require_clean_work_tree) + if ! (require_clean_work_tree "rebase") then warn "Commit or stash your changes, and then run" warn @@ -768,7 +760,7 @@ first and then run 'git rebase --continue' again." record_in_rewritten "$(cat "$DOTEST"/stopped-sha)" - require_clean_work_tree + require_clean_work_tree "rebase" do_rest ;; --abort) @@ -866,7 +858,7 @@ first and then run 'git rebase --continue' again." comment_for_reflog start - require_clean_work_tree + require_clean_work_tree "rebase" "Please commit or stash them." if test ! -z "$1" then diff --git a/git-rebase.sh b/git-rebase.sh index e5df23b..988b3d8 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -416,19 +416,7 @@ else fi fi -# The tree must be really really clean. -if ! git update-index --ignore-submodules --refresh > /dev/null; then - echo >&2 "cannot rebase: you have unstaged changes" - git diff-files --name-status -r --ignore-submodules -- >&2 - exit 1 -fi -diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --) -case "$diff" in -?*) echo >&2 "cannot rebase: your index contains uncommitted changes" - echo >&2 "$diff" - exit 1 - ;; -esac +require_clean_work_tree "rebase" "Please commit or stash them." if test -z "$rebase_root" then diff --git a/git-sh-setup.sh b/git-sh-setup.sh index ae031a1..aa16b83 100644 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -145,6 +145,35 @@ require_work_tree () { die "fatal: $0 cannot be used without a working tree." } +require_clean_work_tree () { + git rev-parse --verify HEAD >/dev/null || exit 1 + git update-index -q --ignore-submodules --refresh + err=0 + + if ! git diff-files --quiet --ignore-submodules + then + echo >&2 "Cannot $1: You have unstaged changes." + err=1 + fi + + if ! git diff-index --cached --quiet --ignore-submodules HEAD -- + then + if [ $err = 0 ] + then + echo >&2 "Cannot $1: Your index contains uncommitted changes." + else + echo >&2 "Additionally, your index contains uncommitted changes." + fi + err=1 + fi + + if [ $err = 1 ] + then + test -n "$2" && echo >&2 "$2" + exit 1 + fi +} + get_author_ident_from_commit () { pick_author_script=' /^author /{ -- 1.7.2.2.409.gdbb11.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Wincent Colaiuta
> Well, I'm not "assuming" that the complaints are justified; I'm talking from 3.5 years of personal experience using Git:
> > - the concept of the "index": learnt it in 30 seconds, and sick of hearing people complain about it > > - terminology related to concepts of "tracking"/"remote(s)": discomfort almost every time I've had to deal with it > I concur. I 'm working with a couple of dozen of people and helping them to learn git and the most confusing part is the tracking/remote because of too many meanings of the same words in use. We are talking about the tracking branch which is "local remote", but we also can create a tracking branch that will track the remote but will be local like: $git branch -t dev origin/dev There should be some different consistent and not inter-crossing naming for the origin's master branch (on the remote side), for the local origin/master and for local master that is a tracking branch. The only way i found so far to explain this is actually via the naming syntax where having / in the name of the branch means remote branch. I was a bit surprised that i can create a local branch with a slash in the name - probably it should be prohibited. In this light pull command not updating the remote ref, but FETCH_HEAD is only adding to the overall confusion (I remember: it is pending change) Thanks, Eugene -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Jakub Narębski
Thank you all for your many and well-thought out replies. I learned a lot.
Jonathan Nieder: > So what would be a better term [for tracking]? Trailing is better than tracking, since it hints at some degree of sloth, but I have not thought this through. (I also think that it may be a strategic mistake to advocate looking for a new name; as long as tracking is used consistently the problem with a misleading metaphor is not so big, and the name change alienates a large group of people whose consent is important.) > How will a person used to e.g. cvs ever adjust if they don't even realize git is different? This comment, and similar from others, makes it clear that I made a mistake in taking up staging versus tracking. It sends a wrong signal about my intentions, and is only a minor detail. This was *not* so difficult to understand, so I shouldn’t have included it. My annoyance here is merely aesthetic and pedagogical. Matthiey Moy: > Git's huge sin, after all (judging from most complaints I see about it), is that It Doesn't Use Exactly The Same Model (and thus Terminology) That CVS Did... My analysis of Git’s wickedness is interestingly different. Git has a clean and simple model that should be very easy to understand. Git’s rhetorical traditions prevent that understanding. Git is really, really hard to learn, no matter where you come from, but there is no inherent reason for that. The steepness of the learning curve (rather than the divergence from other systems’s terminology) is the single biggest complaint against git, evidenced by my own anecdotal evidence from web surfing, and by the Git user survey. It should be viewed as Git’s biggest current problem by an order of magnitude. It makes me think twice and thrice before asking my colleagues to collaborate with me using Git; I will probably learn Mercurial and advocate using that instead—it’s almost as nice, and I don’t feel embarrassed advocating it. Using git for myself is great (now I understand it) but it is unclear if I should invest social capital to convince others to use it as well. The magnitude of how bad this is, and the urgency with which this should be fixed, is clear to everybody—except, naturally, the denizens of this mailing list. Not out of malice or incompetence, but *because of* familiarity. Sverre Rabbelier: > What do you mean with the last part (about `git branch -r`)? The fact > that 'refs/remotes' is not immutable? Well, consider for example the simple obfuscatory mastery of the following line in the user manual: > $ git branch -r # list all remote branches Yes, I get it *now*. And I begin to feel the corruption spreading in my own brain already: I myself start to think of origin/master as a “remote branch”. Give me a few more weeks and I will be completely assimilated in the mindset. (Note to self: submit a patch about this before my assimilation is complete. I already fixed it and committed to my local branch.) Mattiey again: > We already came up with a better wording, namely "upstream", and used in in "git push --set-upstream". Oh, I didn’t know that. I was convinced that “upstream” was cruft from when git was chiefly a tool to help Linus maintain the Linux kernel. Let‘s see if I get this right: The remote-tracking branch “origin/master” is *upstream* (the upstream?) of the local branch “master”, and *tracks* the remote origin’s branch “master”? (local) “master” is downstream of “origin/master”? This would be useful. And @{u} is good. (Does it have an inverse?) I’m not sure I like the particular word, but that’s a minor complaint. ( For completeness: A small terminological quibble is that upstream doesn’t verb well. A bigger conceptual quibble is that this decision is not workflow-neutral. It enforces git’s hierarchical linux-kernel development tradition, rather than embracing a truly distributed model where everybody is the same. When I think of distributed version control I like to think of Alice having a remote-tracking bob/master and Bob having a remote-tracking alice/master. Of course, it is still meaningful for Alice to say “the upstream of bobs_latest_crazy_ideas is bob/master”, and for Bob to say “the upstream of alices_inane_ramblings is alice/master”. But it introduces a notion of hierarchy that is inimical to the concept of distribution, and not workflow-neutral. ) Of course, upstream could be called supercalifragilistic and I would still like it. Consistency is more important than having good metaphors. (But good metaphors would be better, all other things being equal.) Jakup Narebski: > Note that it is not as easy as it seems at first glance. There are *two* such options, which (as you can read in gitcli(7) manpage) have slightly different meaning: Wow. Thanks for pointing this out, I did not know that, and it explains a lot. I must say that to everybody else than a git developer, this state of affairs is a proof that something is wrong, rather than an obstruction for improvement. > I do not think debating on changing the terminology is a particularly productive use of our time. I agree in the sense that *how* the words are used is more important than *which* words are used, and I realise that I should not have put “terminology” in the headline, because that makes it about words, not *explanations* or terminological *discipline*. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Jonathan Nieder-2
Jonathan Nieder <[hidden email]> writes:
> Junio C Hamano wrote: > >> Makes me wonder >> >> - if we can/want to have a logic like this inside verify_filename(); > > Yes, I think so. I was worried that this would be confusing for some > command that looks to the worktree, like git grep without --cached, > but I suspect that worry was unfounded. > > The one case I am worried about is "git rev-parse". What is > "git rev-parse <path>" supposed to be used for? > >> - if we need a corresponding logic in either the previous else/if cascade >> that calls verify_non_filename(), or in verify_non_filename() itself. > > Yes. > > Is it safe to load the index so early? I can imagine a person trying > "git reset" to recover from a corrupted index; are we regressing in > that respect and how would one check for it? It is generally unsafe, I am afraid, and that is one of the reasons why verify_filename() does not look in the index (the other one was "it is merely a safety measure based on heuristics to help users, and no point spending extra code nor cycles", iow, deliberate laziness ;-)), making the proposal of this patch under discussion somewhat iffy. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
|
In reply to this post by Sverre Rabbelier-2
Sverre Rabbelier writes:
> On Mon, Oct 18, 2010 at 15:45, Thore Husfeldt <[hidden email]> wrote: > > The hyphenated *remote-tracking* is a lot better terminology already > > (and sometimes even used in the documentation), because at least it > > doesn't pretend to be a remote branch (`git branch -r`, of course, > > still does). > > What do you mean with the last part (about `git branch -r`)? The fact > that 'refs/remotes' is not immutable? > > > So that single hyphen already does some good, and should > > be edited for consistency. > > If we agree that "remote-tracking" is the way to go, a patch doing > such editing would be very welcome. -- 8< -- From a863e58d240956191c2fa9cbe992aaca5786730b Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra <[hidden email]> Date: Tue, 19 Oct 2010 22:42:05 +0530 Subject: [PATCH] Documentation: Consistently use the hyphenated "remote-tracking" Replace instances of the term "remote tracking" with "remote-tracking" in the documentation for clarity. Reported-by: Thore Husfeldt <[hidden email]> Signed-off-by: Ramkumar Ramachandra <[hidden email]> --- Documentation/config.txt | 2 +- Documentation/fetch-options.txt | 2 +- Documentation/git-gc.txt | 2 +- Documentation/git-log.txt | 2 +- Documentation/git-pull.txt | 2 +- Documentation/git-remote.txt | 4 ++-- Documentation/gittutorial.txt | 6 +++--- Documentation/rev-list-options.txt | 2 +- Documentation/user-manual.txt | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 71ddb6c..736b22f 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -708,7 +708,7 @@ color.diff.<slot>:: color.decorate.<slot>:: Use customized color for 'git log --decorate' output. `<slot>` is one of `branch`, `remoteBranch`, `tag`, `stash` or `HEAD` for local - branches, remote tracking branches, tags, stash and HEAD, respectively. + branches, remote-tracking branches, tags, stash and HEAD, respectively. color.grep:: When set to `always`, always highlight matches. When `false` (or diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index 470ac31..a435c23 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -36,7 +36,7 @@ ifndef::git-pull[] -p:: --prune:: - After fetching, remove any remote tracking branches which + After fetching, remove any remote-tracking branches which no longer exist on the remote. endif::git-pull[] diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt index 315f07e..d6d6833 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.txt @@ -89,7 +89,7 @@ are not part of the current project most users will want to expire them sooner. This option defaults to '30 days'. The above two configuration variables can be given to a pattern. For -example, this sets non-default expiry values only to remote tracking +example, this sets non-default expiry values only to remote-tracking branches: ------------ diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 6d40f00..ff41784 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -116,7 +116,7 @@ git log --follow builtin-rev-list.c:: git log --branches --not --remotes=origin:: Shows all commits that are in any of local branches but not in - any of remote tracking branches for 'origin' (what you have that + any of remote-tracking branches for 'origin' (what you have that origin doesn't). git log master --not --remotes=*/master:: diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt index c50f7dc..33e8438 100644 --- a/Documentation/git-pull.txt +++ b/Documentation/git-pull.txt @@ -26,7 +26,7 @@ With `--rebase`, it runs 'git rebase' instead of 'git merge'. <repository> should be the name of a remote repository as passed to linkgit:git-fetch[1]. <refspec> can name an arbitrary remote ref (for example, the name of a tag) or even -a collection of refs with corresponding remote tracking branches +a collection of refs with corresponding remote-tracking branches (e.g., refs/heads/*:refs/remotes/origin/*), but usually it is the name of a branch in the remote repository. diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index aa021b0..3143c89 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -75,7 +75,7 @@ was passed. 'rename':: -Rename the remote named <old> to <new>. All remote tracking branches and +Rename the remote named <old> to <new>. All remote-tracking branches and configuration settings for the remote are updated. + In case <old> and <new> are the same, and <old> is a file under @@ -84,7 +84,7 @@ the configuration file format. 'rm':: -Remove the remote named <name>. All remote tracking branches and +Remove the remote named <name>. All remote-tracking branches and configuration settings for the remote are removed. 'set-head':: diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt index 1c16066..0982f74 100644 --- a/Documentation/gittutorial.txt +++ b/Documentation/gittutorial.txt @@ -385,7 +385,7 @@ alice$ git fetch bob Unlike the longhand form, when Alice fetches from Bob using a remote repository shorthand set up with 'git remote', what was -fetched is stored in a remote tracking branch, in this case +fetched is stored in a remote-tracking branch, in this case `bob/master`. So after this: ------------------------------------- @@ -402,8 +402,8 @@ could merge the changes into her master branch: alice$ git merge bob/master ------------------------------------- -This `merge` can also be done by 'pulling from her own remote -tracking branch', like this: +This `merge` can also be done by 'pulling from her own remote-tracking +branch', like this: ------------------------------------- alice$ git pull . remotes/bob/master diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index ebc0108..052e64f 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -264,7 +264,7 @@ endif::git-rev-list[] Pretend as if all the refs in `refs/remotes` are listed on the command line as '<commit>'. If `pattern`is given, limit - remote tracking branches to ones matching given shell glob. + remote-tracking branches to ones matching given shell glob. If pattern lacks '?', '*', or '[', '/*' at the end is implied. --glob=glob-pattern:: diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 77eb483..cc65077 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1700,7 +1700,7 @@ may wish to check the original repository for updates and merge them into your own work. We have already seen <<Updating-a-repository-With-git-fetch,how to -keep remote tracking branches up to date>> with linkgit:git-fetch[1], +keep remote-tracking branches up to date>> with linkgit:git-fetch[1], and how to merge two branches. So you can merge in changes from the original repository's master branch with: -- 1.7.2.2.409.gdbb11.dirty > > (Comment: maybe “... but working directory contains untracked files.” > > I realise that “directory” is not quite comprehensive here, because > > files can reside in subdirectories. > > We use "worktree" elsewhere, how about that? $ git grep "worktree" | wc -l 281 $ git grep "working directory" | wc -l 246 $ git grep "working tree" | wc -l 449 Additionally, "working directory" also really refers to a (current) working *directory* in many places. I like "worktree" too, but for consistency I've replaced the inconsistent usage of "working directory" in the UI with "working tree". No, I haven't updated the documentation because it's frankly too painful. -- 8< -- From 7422c2af1ef40c922d8f628715ad96172e4a5734 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra <[hidden email]> Date: Tue, 19 Oct 2010 23:16:04 +0530 Subject: [PATCH] UI: Don't say "working directory" when we really mean "working tree" While in some places "working directory" is used to refer to the (current) working directory, it's incorrectly used in places where Git actually means "working tree" or worktree. Weed out and replace these instances in the UI. Reported-by: Thore Husfeldt <[hidden email]> Signed-off-by: Ramkumar Ramachandra <[hidden email]> --- builtin/apply.c | 2 +- convert.c | 4 ++-- git-filter-branch.sh | 2 +- git-stash.sh | 2 +- setup.c | 2 +- unpack-trees.c | 2 +- wt-status.c | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 23c18c5..9166320 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -2934,7 +2934,7 @@ static int check_to_create_blob(const char *new_name, int ok_if_exists) if (has_symlink_leading_path(new_name, strlen(new_name))) return 0; - return error("%s: already exists in working directory", new_name); + return error("%s: already exists in working tree", new_name); } else if ((errno != ENOENT) && (errno != ENOTDIR)) return error("%s: %s", new_name, strerror(errno)); diff --git a/convert.c b/convert.c index 01de9a8..441708e 100644 --- a/convert.c +++ b/convert.c @@ -131,7 +131,7 @@ static void check_safe_crlf(const char *path, enum action action, */ if (stats->crlf) { if (checksafe == SAFE_CRLF_WARN) - warning("CRLF will be replaced by LF in %s.\nThe file will have its original line endings in your working directory.", path); + warning("CRLF will be replaced by LF in %s.\nThe file will have its original line endings in your working tree.", path); else /* i.e. SAFE_CRLF_FAIL */ die("CRLF would be replaced by LF in %s.", path); } @@ -142,7 +142,7 @@ static void check_safe_crlf(const char *path, enum action action, */ if (stats->lf != stats->crlf) { if (checksafe == SAFE_CRLF_WARN) - warning("LF will be replaced by CRLF in %s.\nThe file will have its original line endings in your working directory.", path); + warning("LF will be replaced by CRLF in %s.\nThe file will have its original line endings in your working tree.", path); else /* i.e. SAFE_CRLF_FAIL */ die("LF would be replaced by CRLF in %s", path); } diff --git a/git-filter-branch.sh b/git-filter-branch.sh index 962a93b..0ab5551 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -110,7 +110,7 @@ OPTIONS_SPEC= if [ "$(is_bare_repository)" = false ]; then git diff-files --ignore-submodules --quiet && git diff-index --cached --quiet HEAD -- || - die "Cannot rewrite branch(es) with a dirty working directory." + die "Cannot rewrite branch(es) with a dirty working tree." fi tempdir=.git-rewrite diff --git a/git-stash.sh b/git-stash.sh index 7561b37..86cf24e 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -179,7 +179,7 @@ save_stash () { git update-ref -m "$stash_msg" $ref_stash $w_commit || die "Cannot save the current status" - say Saved working directory and index state "$stash_msg" + say Saved working tree and index state "$stash_msg" if test -z "$patch_mode" then diff --git a/setup.c b/setup.c index a3b76de..55f8fe3 100644 --- a/setup.c +++ b/setup.c @@ -611,7 +611,7 @@ const char *setup_git_directory(void) die_errno ("Could not jump back into original cwd"); rel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree()); if (rel && *rel && chdir(get_git_work_tree())) - die_errno ("Could not jump to working directory"); + die_errno ("Could not jump to working tree"); return rel && *rel ? strcat(rel, "/") : NULL; } diff --git a/unpack-trees.c b/unpack-trees.c index 803445a..a70b57c 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -934,7 +934,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options } if (o->result.cache_nr && empty_worktree) { - ret = unpack_failed(o, "Sparse checkout leaves no entry on working directory"); + ret = unpack_failed(o, "Sparse checkout leaves no entry on working tree"); goto done; } } diff --git a/wt-status.c b/wt-status.c index fc2438f..89831cb 100644 --- a/wt-status.c +++ b/wt-status.c @@ -95,7 +95,7 @@ static void wt_status_print_dirty_header(struct wt_status *s, color_fprintf_ln(s->fp, c, "# (use \"git add <file>...\" to update what will be committed)"); else color_fprintf_ln(s->fp, c, "# (use \"git add/rm <file>...\" to update what will be committed)"); - color_fprintf_ln(s->fp, c, "# (use \"git checkout -- <file>...\" to discard changes in working directory)"); + color_fprintf_ln(s->fp, c, "# (use \"git checkout -- <file>...\" to discard changes in working tree)"); if (has_dirty_submodules) color_fprintf_ln(s->fp, c, "# (commit or discard the untracked or modified content in submodules)"); color_fprintf_ln(s->fp, c, "#"); @@ -690,7 +690,7 @@ void wt_status_print(struct wt_status *s) ? " (use -u to show untracked files)" : ""); else printf("nothing to commit%s\n", advice_status_hints - ? " (working directory clean)" : ""); + ? " (working tree clean)" : ""); } } -- 1.7.2.2.409.gdbb11.dirty > > Changes to be committed: > > (use "git reset HEAD <file>..." to unstage) > > > > should be > > > > Staged to be committed: > > (use "git unstage <file>" to unstage) > > This would be extra nice since 'git unstage' could also be used in a > fresh repository. [`git unstage` patch still cooking] Sverre: Thanks! Thore: Thanks for the feedback. Please read Documentation/SubmittingPatches and submit more patches. -- Ram -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [hidden email] More majordomo info at http://vger.kernel.org/majordomo-info.html |
| Powered by Nabble | Edit this page |
