{"thread":{"id":"45612","subject":"Why does git-checkout accept a tree-ish?","startedAt":"2017-04-05T23:51:47Z","lastAt":"2017-07-07T19:59:13Z","messageCount":3,"participants":["Dan Fabulich","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"316244","messageId":"EA993AC0-022C-423D-ABD7-4747FA09E7FE@fabulich.com","threadId":"45612","inReplyTo":null,"subject":"Why does git-checkout accept a tree-ish?","fromName":"Dan Fabulich","fromEmail":"dan@fabulich.com","sentAt":"2017-04-05T23:51:40Z","receivedAt":"2017-04-05T23:51:47Z","isPatch":false,"sender":{"key":"dan@fabulich.com","avatar":"https://gravatar.com/avatar/884cee2af623b7675bebdd7b70b13dcb8423150d8f137ec0841859b80a21cd05?d=mp&s=160"},"body":"I was looking back through git's history, trying to figure out why git-checkout has so many features. I was struck by this commit by Junio in 2005.\n\nhttps://github.com/git/git/commit/4aaa702794447d9b281dd22fe532fd61e02434e1\n\n> git-checkout: revert specific paths to either index or a given tree-ish.\n> When extra paths arguments are given, git-checkout reverts only those\n> paths to either the version recorded in the index or the version\n> recorded in the given tree-ish.\n> \n> This has been on the TODO list for quite a while.\n\nPrior to this commit, git-checkout would only switch branches; you could use git-checkout-index to copy files from the index to the working tree. But in this commit, git-checkout not only subsumes the functionality of git-checkout-index but also learns the ability to copy files from an arbitrary branch (now an arbitrary tree-ish) into the working copy *and* the the index. (That was important because git-reset didn't accept <paths> in 2005.)\n\nI think the \"UNIX philosophy\" would have advocated that a new command be created to handle this case, perhaps something like git-checkout-tree. (That would also have eliminated the need to use -- to disambiguate the tree-ish from the paths.)\n\nAnd so I wonder if anybody knows just why git-checkout gained these two features in one commit, without creating a separate command.\n\nI have two guesses:\n\n1) It was pretty easy for Junio to implement as part of git-checkout; just 20 lines of code and a small test.\n\n2) git at the time was distributed as a collection of files, git-checkout, git-reset, etc. and so there was some pressure not to create a new command for fear that it would clutter the filesystem.\n\nAre those the actual reasons? (This seems like it might be a FAQ, but Google failed me searching for git faqs or \"why does git checkout do so many things.\")\n\n-Dan\n\nP.S. I would make a similar argument about adding <paths> support to git-reset, rather than creating a separate command like git-unadd.\n\nhttps://github.com/git/git/commit/2ce633b928f78224a37308f45810e76fefe8df56\nIt was documented a couple of weeks later on Dec 26.\nhttps://github.com/git/git/commit/6934dec89538e054823aadcce08af040bc8dcf79"},{"id":"323967","messageId":"xmqqshi8b04b.fsf@gitster.mtv.corp.google.com","threadId":"45612","inReplyTo":"EA993AC0-022C-423D-ABD7-4747FA09E7FE@fabulich.com","subject":"Re: Why does git-checkout accept a tree-ish?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-07-07T17:57:56Z","receivedAt":"2017-07-07T17:58:07Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dan Fabulich <dan@fabulich.com> writes:\n\n> I was looking back through git's history, trying to figure out why\n> git-checkout has so many features. I was struck by this commit by\n> Junio in 2005.\n>\n> https://github.com/git/git/commit/4aaa702794447d9b281dd22fe532fd61e02434e1\n>\n>> git-checkout: revert specific paths to either index or a given tree-ish.\n>> When extra paths arguments are given, git-checkout reverts only those\n>> paths to either the version recorded in the index or the version\n>> recorded in the given tree-ish.\n>> \n>> This has been on the TODO list for quite a while.\n>\n> Prior to this commit, git-checkout would only switch branches; you\n> could use git-checkout-index to copy files from the index to the\n> working tree. But in this commit, git-checkout not only subsumes\n> the functionality of git-checkout-index but also learns the\n> ability to copy files from an arbitrary branch (now an arbitrary\n> tree-ish) into the working copy *and* the the index. (That was\n> important because git-reset didn't accept <paths> in 2005.)\n> ...\n> And so I wonder if anybody knows just why git-checkout gained\n> these two features in one commit, without creating a separate\n> command.\n\nThe whole thread would explain it, I think.\n\nhttps://public-inbox.org/git/Pine.LNX.4.64.0510171814430.3369@g5.osdl.org/#t\n\n"},{"id":"323975","messageId":"xmqq37a8auig.fsf@gitster.mtv.corp.google.com","threadId":"45612","inReplyTo":"EA993AC0-022C-423D-ABD7-4747FA09E7FE@fabulich.com","subject":"Re: Why does git-checkout accept a tree-ish?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-07-07T19:59:03Z","receivedAt":"2017-07-07T19:59:13Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dan Fabulich <dan@fabulich.com> writes:\n\n> Prior to this commit, git-checkout would only switch branches; you\n> could use git-checkout-index to copy files from the index to the\n> working tree. But in this commit, git-checkout not only subsumes\n> the functionality of git-checkout-index but also learns the\n> ability to copy files from an arbitrary branch (now an arbitrary\n> tree-ish) into the working copy *and* the the index. (That was\n> important because git-reset didn't accept <paths> in 2005.)\n> ...\n> P.S. I would make a similar argument about adding <paths> support\n> to git-reset, rather than creating a separate command like\n> git-unadd.\n\nI do not have a habit of crying over spilt milk for too long, but if\nwe did not have \"git reset <paths>...\" and adding an equivalent\nfeature today, I would guess that we would not have done it as a\ndifferent mode for \"git reset\".  We probably wouldn't have added an\nextra command \"unadd\", either.\n\n\"git checkout --cached [<tree-ish>] <paths>...\" would have been more\nin line with the CLI convention for a command that can act on the\nindex and/or the working tree files (\"--cached\" is the way to make a\nrequest to act only on the index without affecting the working tree\nfiles).\n\nAs to why \"git checkout\" started taking <paths>, the thread referred\nto in my previous response seems to give a better story than I could\nremember ;-).  We were unhappy with checkout-index and the\nsuggestion that was first made publicly reused \"git checkout\".\nWhile I initially showed my reluctance by calling the hypothetical\ncommand \"xxxxxx\" instead of Linus's suggested overloading of\n\"checkout\" in my response in the thread, I think the end-result\nturned out to be not too bad, given that our users understand the\ndifference between \n\n - checking out a branch to work on advancing the history of the\n   branch; and\n\n - checking out a set of paths out of a <tree-ish> to modify the\n   working tree contents while working on advancing the history of\n   the current branch.\n\njust fine.  When doing the former, you would of course want to\npreserve local modifications in your working tree.  When doing the\nlatter, you are asking to overwrite the named paths (checking them\nout of a tree-ish or the index is often done to wipe the mistaken\nattempt to modify it and giving you a clean slate).\n"}]}