{"thread":{"id":"42948","subject":"git-testadd: Execute a command with only the staged changes in Git applied","startedAt":"2016-07-28T16:21:12Z","lastAt":"2016-07-28T23:18:04Z","messageCount":5,"participants":["Øyvind A. Holm","Jakub Narębski"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"292423","messageId":"CAA787r=FH7Sa4qy2A-dy+wug81ZkqOW2KmSuWBE8_3whmNj1pw@mail.gmail.com","threadId":"42948","inReplyTo":null,"subject":"git-testadd: Execute a command with only the staged changes in Git applied","fromName":"Øyvind A. Holm","fromEmail":"sunny@sunbase.org","sentAt":"2016-07-28T16:20:34Z","receivedAt":"2016-07-28T16:21:12Z","isPatch":false,"sender":{"key":"sunny@sunbase.org","avatar":"https://avatars.githubusercontent.com/u/113445?v=4"},"body":"This is a script I created some weeks ago, and I've found it to be\nimmensely useful. Here is a snippet from git-testadd --help:\n\n  If you have lots of unrelated uncommitted changes in the current\n  repository and want to split up the commit, how can you easily check\n  if the changes passes the test suite? With all the other unrelated\n  changes it can be hard to make sure that only relevant changes becomes\n  part of the commit, and that they don't result in regressions. This\n  script clones the repository to the directory \".testadd.tmp\" in the\n  current directory and applies the staged chenges there (unless\n  -u/--unmodified or -p/--pristine is specified), chdirs to the same\n  relative directory in the clone and executes the command specified on\n  the command line there.\n\nThe script is well-tested, and also have a test suite you can run to\nmake sure it works on your *nix system. Place git-testadd.t in a\nsubdirectory one level under the script location, chdir to that\ndirectory and execute \"./git-testadd.t\". It also works with binary\nfiles.\n\nAvailable from\n\n  https://gitlab.com/sunny256/utils/raw/master/git-testadd\n  https://gitlab.com/sunny256/utils/raw/master/tests/git-testadd.t\n\nIt's also on GitHub, just replace \"gitlab\" with \"github\" in the URLs.\nAnd of course, ideas and patches for new functionality/fixes are always\nwelcome.\n\n        Øyvind\n"},{"id":"292427","messageId":"CAA787rmDb+1=4RCscvo1rZWSt=tUQSm5wrFet-=PhRKZcf9x5A@mail.gmail.com","threadId":"42948","inReplyTo":"xmqqlh0lsoq6.fsf@gitster.mtv.corp.google.com","subject":"Re: git-testadd: Execute a command with only the staged changes in Git applied","fromName":"Øyvind A. Holm","fromEmail":"sunny@sunbase.org","sentAt":"2016-07-28T16:56:52Z","receivedAt":"2016-07-28T16:57:27Z","isPatch":false,"sender":{"key":"sunny@sunbase.org","avatar":"https://avatars.githubusercontent.com/u/113445?v=4"},"body":"On 28 July 2016 at 18:37, Junio C Hamano <gitster@pobox.com> wrote:\n> Øyvind A. Holm <sunny@sunbase.org> writes:\n> > This is a script I created some weeks ago, and I've found it to be\n> > immensely useful. Here is a snippet from git-testadd --help:\n> >\n> >   If you have lots of unrelated uncommitted changes in the current\n> >   repository and want to split up the commit, how can you easily\n> >   check if the changes passes the test suite? With all the other\n> >   unrelated changes it can be hard to make sure that only relevant\n> >   changes becomes part of the commit, and that they don't result in\n> >   regressions. This script clones the repository to the directory\n> >   \".testadd.tmp\" in the current directory and applies the staged\n> >   chenges there (unless -u/--unmodified or -p/--pristine is\n> >   specified), chdirs to the same relative directory in the clone and\n> >   executes the command specified on the command line there.\n>\n> So in short, this solves the same problem as \"git stash --keep\" but in\n> a more scalable way, in the sense that \"git stash --keep\" allows you\n> to instantiate what you have in the index so that your working tree\n> can be used for such a test, but you cannot do anything else while you\n> are waiting for the test to finish, and \"testadd\" allows you to keep\n> hacking in the working tree while a test runs in its own temporary\n> checkout (and presumably you can have more than one running, which\n> would allow you to scale more)?\n\nThat's correct, the test clone is entirely separated from the working\ncopy, and you can keep working while the tests are running in the clone.\nCombined with git-gui and/or \"git add -p/git reset -p\", it's easy to\ntweak the staged changes until things are ok.\n\nAlso, there is a -l/--label option that creates a clone directory with\nthe name \".testadd-[LABEL].tmp\", so you can have several test clones at\nthe same time, all with different staged changes. There is also a\n-r/--ref option that tries to apply the staged changes onto another\ncommit, and the command will only run if the apply succeeds. Also, this\nwon't create dangling heads like \"git stash --keep\" does.\n\n        Øyvind\n"},{"id":"292444","messageId":"579A5D97.7080708@gmail.com","threadId":"42948","inReplyTo":"CAA787rmDb+1=4RCscvo1rZWSt=tUQSm5wrFet-=PhRKZcf9x5A@mail.gmail.com","subject":"Re: git-testadd: Execute a command with only the staged changes in Git applied","fromName":"Jakub Narębski","fromEmail":"jnareb@gmail.com","sentAt":"2016-07-28T19:31:35Z","receivedAt":"2016-07-28T19:32:08Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"W dniu 2016-07-28 o 18:56, Øyvind A. Holm pisze:\n> On 28 July 2016 at 18:37, Junio C Hamano <gitster@pobox.com> wrote:\n>> Øyvind A. Holm <sunny@sunbase.org> writes:\n\n>>> This is a script I created some weeks ago, and I've found it to be\n>>> immensely useful. Here is a snippet from git-testadd --help:\n>>>\n>>>   If you have lots of unrelated uncommitted changes in the current\n>>>   repository and want to split up the commit, how can you easily\n>>>   check if the changes passes the test suite? With all the other\n>>>   unrelated changes it can be hard to make sure that only relevant\n>>>   changes becomes part of the commit, and that they don't result in\n>>>   regressions. This script clones the repository to the directory\n>>>   \".testadd.tmp\" in the current directory and applies the staged\n>>>   chenges there (unless -u/--unmodified or -p/--pristine is\n>>>   specified), chdirs to the same relative directory in the clone and\n>>>   executes the command specified on the command line there.\n>>\n>> So in short, this solves the same problem as \"git stash --keep\" but in\n>> a more scalable way, in the sense that \"git stash --keep\" allows you\n>> to instantiate what you have in the index so that your working tree\n>> can be used for such a test, but you cannot do anything else while you\n>> are waiting for the test to finish, and \"testadd\" allows you to keep\n>> hacking in the working tree while a test runs in its own temporary\n>> checkout (and presumably you can have more than one running, which\n>> would allow you to scale more)?\n> \n> That's correct, the test clone is entirely separated from the working\n> copy, and you can keep working while the tests are running in the clone.\n> Combined with git-gui and/or \"git add -p/git reset -p\", it's easy to\n> tweak the staged changes until things are ok.\n\nI wonder if using `git worktree` instead of `git clone` (well, local\nclone uses hardlinks, so it is not that costly as it looks like) would\nbe a better solution.\n \n> Also, there is a -l/--label option that creates a clone directory with\n> the name \".testadd-[LABEL].tmp\", so you can have several test clones at\n> the same time, all with different staged changes. There is also a\n> -r/--ref option that tries to apply the staged changes onto another\n> commit, and the command will only run if the apply succeeds. Also, this\n> won't create dangling heads like \"git stash --keep\" does.\n\nNice.\n\n\n"},{"id":"292462","messageId":"CAA787rm+qLig6mzHw0NjNDt-6HF_77FOwmg5dBBOdwbqo3wP6A@mail.gmail.com","threadId":"42948","inReplyTo":"579A5D97.7080708@gmail.com","subject":"Re: git-testadd: Execute a command with only the staged changes in Git applied","fromName":"Øyvind A. Holm","fromEmail":"sunny@sunbase.org","sentAt":"2016-07-28T22:31:27Z","receivedAt":"2016-07-28T22:32:02Z","isPatch":false,"sender":{"key":"sunny@sunbase.org","avatar":"https://avatars.githubusercontent.com/u/113445?v=4"},"body":"On 28 July 2016 at 21:31, Jakub Narębski <jnareb@gmail.com> wrote:\n> W dniu 2016-07-28 o 18:56, Øyvind A. Holm pisze:\n> > Øyvind A. Holm <sunny@sunbase.org> writes:\n> > > This is a script I created some weeks ago, and I've found it to be\n> > > immensely useful. Here is a snippet from git-testadd --help:\n> > > [...]\n> > >   This script clones the repository to the directory\n> > >   \".testadd.tmp\" in the current directory and applies the staged\n> > >   chenges there (unless -u/--unmodified or -p/--pristine is\n> > >   specified), chdirs to the same relative directory in the clone\n> > >   and executes the command specified on the command line there.\n> >\n> > That's correct, the test clone is entirely separated from the\n> > working copy, and you can keep working while the tests are running\n> > in the clone. Combined with git-gui and/or \"git add -p/git reset\n> > -p\", it's easy to tweak the staged changes until things are ok.\n>\n> I wonder if using `git worktree` instead of `git clone` (well, local\n> clone uses hardlinks, so it is not that costly as it looks like) would\n> be a better solution.\n\nThat's an interesting idea. Have to test it out. This is the result from\nthe current master in linux.git:\n\nWith clone:\n\n  $ time git testadd pwd\n  git-testadd: Using \".testadd.tmp\" as destination directory\n  Cloning into '.testadd.tmp'...\n  done.\n  Checking out files: 100% (55256/55256), done.\n  git-testadd: Applying staged changes\n\n  git-testadd: Executing \"pwd\" in /home/sunny/src/test-wt/.testadd.tmp\n  /home/sunny/src/test-wt/.testadd.tmp\n\n  real    0m10.464s\n  user    0m5.983s\n  sys     0m2.790s\n  $\n\nWith worktree:\n\n  $ time git worktree add testaddtmp\n  Preparing testaddtmp (identifier testaddtmp)\n  Checking out files: 100% (55256/55256), done.\n  HEAD is now at 194dc87 Add braces to avoid \"ambiguous ‘else’\" compiler\n  warnings\n\n  real    0m10.343s\n  user    0m6.010s\n  sys     0m2.523s\n  $\n\nBoth tests were run with cold cache (\"echo 3 >/proc/sys/vm/drop_caches\"\nas root). It seems as there's no difference, and that git clone is as\nfast as it can get without breaking physical laws. And we probably\nshouldn't do that. :)\n\nZ poważaniem,\nØyvind\n"},{"id":"292463","messageId":"CAA787rnugsnAqK6iH_UZMQRhdpnjJ6NN0x8aaVn7e9GAE88=jQ@mail.gmail.com","threadId":"42948","inReplyTo":"xmqqzip1pew5.fsf@gitster.mtv.corp.google.com","subject":"Re: git-testadd: Execute a command with only the staged changes in Git applied","fromName":"Øyvind A. Holm","fromEmail":"sunny@sunbase.org","sentAt":"2016-07-28T23:17:27Z","receivedAt":"2016-07-28T23:18:04Z","isPatch":false,"sender":{"key":"sunny@sunbase.org","avatar":"https://avatars.githubusercontent.com/u/113445?v=4"},"body":"On 29 July 2016 at 00:38, Junio C Hamano <gitster@pobox.com> wrote:\n> Øyvind A. Holm <sunny@sunbase.org> writes:\n> > Jakub Narębski <jnareb@gmail.com> wrote:\n> > > I wonder if using `git worktree` instead of `git clone` (well,\n> > > local clone uses hardlinks, so it is not that costly as it looks\n> > > like) would be a better solution.\n> >\n> > That's an interesting idea. Have to test it out. This is the result\n> > from the current master in linux.git:\n> >\n> > With clone:\n> > ...\n> > With worktree:\n> > ...\n> >\n> > Both tests were run with cold cache (\"echo 3\n> > >/proc/sys/vm/drop_caches\" as root). It seems as there's no\n> > >difference, and that git clone is as fast as it can get without\n> > >breaking physical laws. And we probably shouldn't do that. :)\n>\n> I expect that writing the 55k+ files in the working tree would\n> dominate the cost.  Local clone would make some hardlinks in .git\n> (including ones in .git/object/*) but the cost of that would not be\n> too high as long as the repository is well packed; \"git worktree\"\n> would reduce that part of the cost from \"git clone\", but both incur\n> the cost of \"checkout\", i.e. actually populating the new working tree.\n>\n> Does the test directory even need to look anything like Git?  In other\n> words, would it suffice if it resembled the result of running \"git\n> archive | tar xf -\"?  I suspect that it would not make much\n> difference, either, for the same reason, though ;-).\n\nUsing git archive saved 1.6 seconds:\n\n  $ mkdir testdir; git archive HEAD | (cd testdir && time tar x)\n\n  real    0m8.881s\n  user    0m0.440s\n  sys     0m2.740s\n  $\n\nBut when .git is missing in the subdir, git apply doesn't work. Can't\nthink of any way to get that to work without involving patch(1) and\nfriends, and then the binary diffs goes out of the window.\n\nBut I'm quite satisfied with 10.4 seconds with cold diskcache and >55K\nfiles. Very impressive, actually.\n\n- Øyvind\n"}]}