I've got a git history like so:
commit 027dbda16679e8c737c8ec63676aa564807cfaeb (HEAD -> master)
Author: Camden Narzt <c.narzt@me.com>
Date: Thu Dec 19 15:36:42 2024 -0700
migrate homebrew stuff into tap
update setup script for new tap
commit 53d1c2147f78144098c3fc7c62f6a6f6e00063e7
Author: Camden Narzt <c.narzt@me.com>
Date: Wed Nov 20 23:24:06 2024 -0700
don’t push
commit 3fbb7f8af3870237627ae7d0e027697499ffa74b
Author: Camden Narzt <c.narzt@me.com>
Date: Wed Dec 18 12:42:15 2024 -0700
bump colima config
commit 53d1c2147f78144098c3fc7c62f6a6f6e00063e7
contains stuff I don't want to push, but which I put in a commit in order to be able to work with the history more easily (yes, I should have stashed the changes instead, my bad). I do not want to lose the changes in 53d1c2147f78144098c3fc7c62f6a6f6e00063e7
, but do not want to keep them in the position they are in, in the history, as I'd like to push everything else.
When I run: git rebase -i 3fbb7f8a
and move commit 53d1c2147f78144098c3fc7c62f6a6f6e00063e7
to the end so that it is the latest commit, I get the following error from git:
error: The following untracked working tree files would be overwritten by checkout:
homebrew/Brewfile
homebrew/Brewfile.lock.json
homebrew/emacs-test.el
Please move or remove them before you switch branches.
Aborting
error: could not detach HEAD
The files mentioned in the error message were deleted, and then replaced with the contents of the submodule in commit 027dbda16679e8c737c8ec63676aa564807cfaeb
. I would like to use the files from the submodule going forward. Strangely, not all files that were moved into the submodule are mentioned in the error.
How can I move commit 53d1c2147f78144098c3fc7c62f6a6f6e00063e7
to the end, so that I can push the other commits to the remote?
Commit 53d1c2147f78144098c3fc7c62f6a6f6e00063e7
does not involve the files mentioned in the error at all.
Here's the files from the commit that introduced the submodule:
.gitmodules
Formula/awscli.rb
Formula/bdsup2sub.rb
Formula/fakeapxs.rb
Formula/libipt.rb
Formula/libxed.rb
Formula/mbuild.rb
Formula/pam-duress.rb
Formula/tiny_php.rb
Formula/vobsub2srt.rb
homebrew
homebrew/Brewfile
homebrew/Brewfile.lock.json
homebrew/Formula
homebrew/bin
homebrew/emacs-test.el
setup.sh
usr/local/bin/brew-baggage
usr/local/bin/brew-bottle-outdated
usr/local/bin/brew-clean
usr/local/bin/brew-junk
setup.sh
was modified, .gitmodules
was added, homebrew
was a directory that was replaced with the submodule, all others were deleted.
(yes, I should have stashed the changes instead, my bad)
I strongly disagree, you're doing good! Stash is bad and you should absolutely not use that. Instead continue checking in this as temporary commits like you already do.
This is the proper way of handling your "don't push" changes, you are only bit by a conflict due to the introduction of a submodule, and this problem would occur for any interactive rebase when moving a commit from before commit 027dbda1 to after commit 027dbda1.
My handling would be:
git branch move_prep 53d1c2
git switch move_prep
git rm homebrew/Brewfile homebrew/Brewfile.lock.json homebrew/emacs-test.el
git commit -m "-- remove homebrew files --"
git revert HEAD
git diff move_prep 53d1c2 # Will show no changes
Now you want to rebase your master
branch containing commit 027dbda166 to be on top of branch move_prep
. Since that branch is identical with commit 53d1c2 you will encounter no conflicts.
git branch master.backup master
git rebase move_prep master
Now you start the first interactive rebase and change the line with "-- remove homebrew files --" to fixup
so that it joins the "don't push" commit to a new commit that does not contain the files that are moves to the submodule, and thus this new commit now can be moved to after the submodule is introduced without any problems.
# On master branch
git rebase -i 3fbb7f8af
pick 53d1c21 don’t push
fixup 1111111 -- remove homebrew files --
pick 2222222 Revert commit 1111111
pick 3333333 migrate homebrew stuff into tap
With this done we have a new 4444444 "don’t push" commit that can be moved without problems (and the corresponding revert should be dropped). So start the second interactive rebase
git rebase -i 3fbb7f8af
and change from
pick 4444444 don’t push
pick 2222222 Revert commit 1111111
pick 3333333 migrate homebrew stuff into tap
to
pick 3333333 migrate homebrew stuff into tap
pick 4444444 don’t push
and now your master
branch should be like you wanted (and you can delete the move_prep
and master.backup
branches).
git diff master.backup master # Should show no difference
All the above depends on the commit moved not changing any of the files that live in the submodule. If any such files were modified those changes would be lost (in the outer repository). To keep them I think I would have attempted a combination of git format-patch
(on commits where the homebrew changes has been extracted as the only changes), edit file names in the patch files and then git am
inside the submodule.