3

Is there a way/command on git to "distribute" the changes made to some files to the last commit that modified each file?

On many occasions I notice a small typo (mostly on comments: missing comma, closing a parenthesis, some small grammar error... ) in already committed files. I would like to fixup the last commit on each file to add the small fix. Is that possible without having to manually do a commit, run rebase --interactive, move the commit up, mark it as a fixup of the previous commit...

For instance: Let's say I have this situation:

Commit A: to add a new feature.   0xa1b2c3         2021/03/10 00:00:00
     |-> last commit that modified file '/home/borrajax/projects/feature.py'

Commit B: to test the feature.    0xd4e5f6         2021/03/10 00:05:00
     |-> last commit that modified file '/home/borrajax/projects/test_feature.py'

Commit C: something unrelated.    0x112233         2021/03/10 00:10:00
     |-> doesn't alter 'feature.py' or 'test_feature.py'

Then, I fix some small typos in both feature.py and test_feature.py

Is there a way of saying "add these small changes on file feature.py to Commit A" and "add these small changes on file test_feature.py to commit B" (keeping the commit order A -> B -> C)

What I currently do is:

  1. Adding the changes on feature.py into a commit like "Fixup Commit A"
  2. Adding the changes on test_feature.py into a commit like "Fixup commit B"
  3. Run a rebase --interactive
  4. Move the "Fixup..." commits underneath the commits that I want to fix ("Fixup Commit A" under "Commit A: to add..." and "Fixup commit B" under "Commit B: to test...")
  5. Mark them as fixupsin the --interactive editor.

This is rather time consuming and pretty error prone.

I have read these other two S.O questions (Git distribute fixup commit to original commits and git: squash/fixup earlier commit) but I don't think the proposed solutions do quite what I'm looking for (maybe I'm wrong, and they do, though...)

Savir
  • 17,568
  • 15
  • 82
  • 136
  • You can edit the last commit with `git commit --amend` but I would recommend you to just create a new commit. – dan1st Mar 10 '21 at 20:46
  • Is this with published or unpublished history? I don't recommend fixing up published history; if it's unpublished, I presume you'll want to stop at the point your current dev branches diverges from its upstream branch. Is that correct? – John Kugelman Mar 10 '21 at 20:47
  • What if you've modified a file twice in separate commits? Are you sure you want to always apply the fixes to the latest commit? Maybe it should leave those changes alone, or prompt you to decide. – John Kugelman Mar 10 '21 at 20:50
  • @JohnKugelman It's unpublished. And indeed, the idea would be changing "my" commits only... That shouldn't be too problematic because I'd know for sure (being careful) that I modified the file in one of those "commits of mine". As for the second (very good) question, yeah: for what I'm currently looking the latest commit would suffice. It's only minor fixes (typos in comments mostly) what I'd be doing this way. – Savir Mar 10 '21 at 23:28

1 Answers1

3

Is that possible without having to manually do a commit, run rebase --interactive, move the commit up, mark it as a fixup of the previous commit...

Yes, rebase will do this for you. See its --autosquash option.

  1. Mark your commits with git commit --fixup=<ref> pointing to the commit you want to fix up. (Message-search syntax can be very handy: --fixup=@^{/somewordfromitssubject}.)
  2. Create as many fixup commits as you want.
  3. git rebase -i --autosquash theoldestfixedupcommit^.
jthill
  • 55,082
  • 5
  • 77
  • 137
  • So it's a noninteractive interactive rebase! – matt Mar 10 '21 at 22:12
  • @matt haha. I don't remember, but I think it still brings up the pick list for you, it just does the tedious automatable bits for you first. – jthill Mar 10 '21 at 23:14
  • This is great! Thank you! – Savir Mar 11 '21 at 18:34
  • yvw. by the way, you can also commit just a single file regardless of what's staged, the kind of git-r-dun work flow you're after is *exactly* the target Git's aiming at too. – jthill Mar 11 '21 at 18:54