Vic Seedoubleyew
Vic Seedoubleyew

Reputation: 10556

Save work into several commits

Most of the time, when doing some work, one ends up with changes that should be saved into different commits.

I am looking for best practices for how to do that in a good way.

Of course, the basic answer is to use git add -p.

The problem with that basic answer is that it doesn't enable to test a given state of the repository before committing. Very often, this would mean forgetting to add some imports, or forgetting a dependency between some staged code and some unstaged parts. As a result, a given commit would not pass a build.

Thus I am looking for a way to create several commits, with the ability to run tests for each commit.

The workflows I have tried so far are the following:

Workflow 1: commit, stash then test

As long as there is more than 1 commit to do with current changes, repeat:

The main problem I see with this workflow is the fact that it doesn't make a lot of sense to commit something without having tested it, knowing that it is likely to be amended shortly after.

Workflow 2: stash, test then commit

As long as there is more than 1 commit to do with current changes, repeat:

The main problem I find with that workflow, is the fact that git stash pop often fails with a conflict. That results in having to redo git add -p on all the conflict files, which can be very time consuming. This happens among other things when trying to add only part of a new file.

The question

Are there other better practices for saving into several commits while testing each one ?

Upvotes: 4

Views: 167

Answers (2)

maaartinus
maaartinus

Reputation: 46482

Forget stash, use interactive rebase. Commit everything as needed and clean up the mess later.

I'd suggest using git gui to create the commits, but that's a minor point. After a while I get a list of commits like

Implement feature A
Refactor mess B
f A 1
f A 2
f B 3
Improve formatting
f A 4
f B 5

where "f A" means "fixup for A". Then I call

git rebase -i

or maybe

git rebase -i HEAD~8

get a list of commits and reorder them like

Improve formatting
Implement feature A
f A 1
f A 2
f A 4
Refactor mess B
f B 3
f B 5

I do this reordering in many small steps, just in case it fails. I use git diff ORIG_HEAD in order to verify that the final version stayed the same.

As the last step I change "pick" to "f" (fixup) so that I end up with three commits only.

For running tests on the intermediate steps, you can also use rebase. Just replace "pick" with "e" (edit), so that git stops after each commit (use git rebase --continue to continue to the next commit).

When doing such a commit cleanup, I usually run the tests last as they usually pass and, in case they don't, the fix is usually obvious.

When rebasing, be careful not to change commits pushed to a shared repository.

Upvotes: 1

phd
phd

Reputation: 94809

The best answer is CI (continuous integration) server. You push as many commits as you want, CI server pulls the branch, checkout commits one by one and run tests on every commit.

Upvotes: 0

Related Questions