Magit: Enable staged new files to be treated as if they had initially been staged with --intent-to-add

Created on 19 Jan 2017  Â·  4Comments  Â·  Source: magit/magit

(Edit: For anyone reading this after the fact, my initial statement that one can "subsequently unstage only parts of it if desired" was completely false, so most of what I wrote here was based on a bad assumption.)


We can already stage new files with C-u s instead of s to trigger the --intent-to-add behaviour (#2638), and then stage only parts of the file, and subsequently unstage only parts of it if desired.

It would be really nice if, after staging an untracked file with just s, we could simply unstage hunks of the staged file as if we had originally gone through the sequence:

  • C-u s (for the untracked file)
  • s (for the entire unstaged file)

At present attempting to unstage a hunk results in the error:

128 git … apply --reverse --cached -p0 --ignore-space-change -
fatal: new file FOO depends on old contents

I don't know whether there's some direct approach to achieving this, or if magit would need to:

  1. unstage the file
  2. add it back with --intent-to-add
  3. stage the entire file
  4. finally apply the user's requested change to unstage a given hunk

Obviously if the user was unstaging the entire file (after staging normally, without intent-to-add), it would then need to return to an untracked state rather than an intent-to-add state; however it would be nice to have the ability to move directly from "staged without intent-to-add" to "entire file unstaged with intent-to-add" in a single step, and (analogous to C-u s) I thought that C-u u might be a good binding for this?

I'm not sure if there are pitfalls to this entire notion that I'm not seeing. I did wonder whether Magit should prompt the user to confirm any move to a state based on intent-to-add, but I'm not sure it's necessary.

If confirmation from the user is needed, perhaps an explicit C-u u should simply be required in all cases -- for unstaging hunks as well as for the entire file. That would be a little less magical, but potentially a safer interface if there are some dangers I've not thought about. If Magit could detect the error when attempting to unstage a hunk from a normally-staged new file, and point out the C-u u binding, users would learn about it easily enough.

feature request

Most helpful comment

I've just noticed that Magit's ediff integration provides a great workaround for the inability to unstage selected parts in this scenario.

  • Type e on the staged file
  • Move to the .~index~ window, which contains the staged changes
  • Edit the content directly (but don't try to save the buffer)
  • Exit ediff with q from the control buffer
  • Confirm to Magit that you wish to update the index
  • Profit!

All 4 comments

I don't know whether there's some direct approach to achieving this, or if magit would need to:

  1. unstage the file
  2. add it back with --intent-to-add
  3. stage the entire file
  4. finally apply the user's requested change to unstage a given hunk

That does not work. Even if I do:

  1. --indent-to-add
  2. stage parts of the file (hoping that would preserve some intent-to-add-iness)
  3. unstage parts of the staged part

I still get the same error.

The only possible approach I see is to create a commit use a discard to perform the unstage, and then somehow remove the commit while maintaining the intended index and not messing with the file in the working tree. Sounds tricky.

it would be nice to have the ability to move directly from "staged without intent-to-add" to "entire file unstaged with intent-to-add" in a single step, and (analogous to C-u s) I thought that C-u u might be a good binding for this?

That should be doable, though having to u C-u s instead of just C-u u doesn't sound that much worse for an action the probably isn't required very often.

I have implemented the C-u u kludge in xx/keep-intend-to-add but have decided to not merge that.

u on parts of a newly added file should just work and the place where that should be made possible is git (faking it on Magit's side is just to hacky). This smells like an unhandled edge and you should probably bring this up on the Git mailing-list.

I've just noticed that Magit's ediff integration provides a great workaround for the inability to unstage selected parts in this scenario.

  • Type e on the staged file
  • Move to the .~index~ window, which contains the staged changes
  • Edit the content directly (but don't try to save the buffer)
  • Exit ediff with q from the control buffer
  • Confirm to Magit that you wish to update the index
  • Profit!

Thanks for the tip!

Was this page helpful?
0 / 5 - 0 ratings