Repository navigation
Avoid conflicts and duplicate lines when moving a patch to an earlier commit - #6167
Open
stefanhaller wants to merge 8 commits into
Open
stefanhaller wants to merge 8 commits into
stefanhaller wants to merge 8 commits into
Conversation
When moving a custom patch to an earlier commit, or into a new commit before the original one, lazygit applies the patch to the earlier commit and then replays the original commit unchanged. It relies on git noticing during the replay that the patch's changes are already there. This doesn't always work: - If the patch contains only some of several adjacent added lines, replaying the original commit stops with a conflict. - If git can place the patch's added lines in two positions because they repeat the line after them, the replay may put them in the other position than the patch did. Git then keeps both copies, and the file ends up containing the patch's lines twice. There's no conflict, so this goes unnoticed. When moving into a new commit before the original one, the conflict of the first case doesn't show the usual "Conflicts!" popup; lazygit focuses the commits panel instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If moving a custom patch into a new commit before the original one results in a conflict, lazygit shows the "Conflicts!" popup, but then immediately focuses the commits view. This closes the popup, and the user is left in a rebase that is stopped at a conflict without being told about it. The test uses a pre-commit hook that changes a file of the new commit; this makes picking the original commit conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If the patch comes from a merge commit, moving it to a later commit leaves the user in a rebase that is stuck before its first todo. Moving it to an earlier commit, or into a new commit before the merge, finishes, but with surprising results. The rebase doesn't replay a merge commit; it recreates it from its parents. If the patch contains changes from the merged branch, the commits on that branch that made them become empty. And a new commit "before" the merge ends up at the tip of the merged branch. Moving a patch to a later merge commit gets stuck in the same way. Moving a patch to a merge commit isn't useful in either direction, so disable both. The other patch commands amend the merge commit itself and work fine, so they stay enabled. They are useful for removing changes that were added to a merge commit by accident. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The next commit uses this to replay a modified copy of a commit in place of the original one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… commit When moving a custom patch to an earlier commit, we apply the patch to the earlier commit and then let the rebase pick the commit that the patch came from, unchanged. This relies on git noticing during the pick that the patch's changes are already there. If the patch contains only some of several adjacent added lines, git doesn't notice, and the pick stops with a conflict. If git can place the patch's added lines in more than one position, it may place them differently for the pick than for the patch. It then adds them a second time, without any conflict. Make the rebase pick a copy of the source commit instead. The copy has the same tree, author and message, but its parent is the original parent with the patch applied. Picking it only replays the source commit's changes minus the patch, so git no longer has to recognize the patch as already applied. Create the copy with plumbing commands and a temporary index; this doesn't touch the working tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mmit before Moving a custom patch into a new commit before the original one has the same problem as moving it to an earlier commit. After committing the patch, the rebase picks the original commit unchanged and relies on git noticing that the patch is already there. Make the rebase pick a copy of the original commit whose parent already contains the patch, as we do when moving to an earlier commit. Here, the copy's parent normally has the same tree as the new commit, so picking the copy doesn't conflict. Only a commit hook that changes the new commit's files could make it conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The handlers for moving the patch into a new commit before or after the original one differ only in the git command they call. The next commit fixes a bug that both have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If moving a custom patch into a new commit stops at a conflict, CheckMergeOrRebase shows the "Conflicts!" popup. The handler then focused the commits view anyway, and this closed the popup. Only focus the commits view if the operation finished. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When moving a custom patch to an earlier commit, or into a new commit before the original one, lazygit applies the patch to the earlier commit and then replayed the original commit unchanged. It relied on git noticing during the replay that the patch's changes are already there. This doesn't always work:
Fix this by making the rebase pick a copy of the source commit instead. The copy has the same tree, author and message, but its parent is the original parent with the patch applied. Picking it only replays the source commit's changes minus the patch, so git no longer has to recognize the patch as already applied.