SITUATION: When making a Pull Request, I want the receiver to be able to understand what changes it makes. I find that squashing them into one commit can be confusing, especially if:
there are edits to code which is also moved - diff renders this as wholesale deletion and addition, not highlighting the edits.
code is added to a series of similar sections, e.g. case statements, cascading ifs, yacc productions - diff often reconstructs the change as overlapping sections (e.g. instead of adding a section, it uses the beginning of the previous section, add a new ending and another beginning, then uses the finishing of that previous section); adds the new codean ending, and in some cases, picks out a few minor similarities then deletes and insert a mass of identical code. (I realize diff uses LCS and is amazingly fast - but sometimes its result is hard to fathom, even when considering diff isn't syntax-aware and can't recognize the code "sections" you see).
BTW: I use git diff --color-words --ignore-space-change
, which is great, but also mis-reconstructs, can hide detail - and I'm concerned that the recipient might use plain git diff
and see something quite different (they can reconstruct differently).
TASK: OK, so the obvious solution to this is to divide up the Pull Request into separate commits. Sometimes, these can be the actual commits I started with, so all I need do is not rebase/squash in the first place. But I'm finding that even then, the diffs can be unclear (especially for reason (2) above), and I need to separate them further.
The obvious way to do this is to use
git add --patch/-p
. However, patches are hard to work with for overlapping changes - you can divide and even edit the hunks, but it's somewhat mindbending to think in terms of reversing diffs when the change you want combines addition, deletion and common code.What I've actually done is to edit the file directly: deleting the part I don't want and committing that; then undoing that deletion (with my editor), and committing that. Working in terms of the actual source is much clearer and more intuitive than working in terms of the diffs - but it feels like I'm fighting against git and doing it wrong (also, it seems accident-prone to rely on editor undo).
It occurs to me to instead first
git stash
the file, and prepare the first commit by deleting the part I don't want; thengit stash apply
to "undo" that delete to prepare the second commit. But I'm not sure that you can do that in the middle of arebase
(haven't tried it yet).
QUESTION: It's taking me hours to all do this... I guess I'll improve with practice but... Am I on the right track? Is there a better way? Can you prevent mis-reconstructed diffs in the first place? Am I working too hard for clarity?
(To be fair, this was many edits on subtle and complex code done a while ago - and spending these hours revealed deeper insights.)