mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 12:25:47 +02:00
Drop update-ref todos pointing to head (#3456)
- **PR Description** The rebase.updateRefs feature of git is very useful to rebase a stack of branches and keep everything nicely stacked; however, it is usually in the way when you make a copy of a branch and want to rebase it "away" from the original branch in some way or other. For example, the original branch might sit on main, and you want to rebase the copy onto devel to see if things still compile there. Or you want to do some heavy history rewriting experiments on the copy, but keep the original branch in case the experiments fail. Or you want to split a branch in two because it contains two unrelated sets of changes; so you make a copy, and drop half of the commits from the copy, then check out the original branch and drop the other half of the commits from it. In all these cases, git's updateRefs feature insists on moving the original branch along with the copy in the first rebase that you make on the copy. I think this is a bug in git, it should create update-ref todos only for branches that point into the middle of your branch (because only then do they form a stack), not when they point at the head (because then it's a copy). I had a long discussion about this on the git mailing list [1], but people either don't agree or don't care enough. So we fix this on our side: whenever we start a rebase for whatever reason, be it interactive, non-interactive, or behind-the-scenes, we drop any update-ref todos that are at the very top of the todo list, which fixes all the above-mentioned scenarios nicely. I will admit that there's one scenario where git's behavior is the desired one, and the fix in this PR makes it worse: when you create a new branch off of an existing one, with the intention of creating a stack of branches, but before you make the first commit on the new branch you realize some problem with the first branch (e.g. a commit that needs to be reworded or dropped). It this case you do want both branches to be affected by the change. In my experience this scenario is much rarer than the other ones that I described above, and it's also much easier to recover from: just check out the other branch again and hard-reset it to the rebased one. [1] https://public-inbox.org/git/354f9fed-567f-42c8-9da9-148a5e223022@haller-berlin.de/
This commit is contained in:
commit
0a5e9b2d60
25 changed files with 250 additions and 33 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -6,9 +6,6 @@
|
|||
# Hidden
|
||||
.*
|
||||
|
||||
# TODO
|
||||
TODO.*
|
||||
|
||||
# Notes
|
||||
*.notes
|
||||
|
||||
|
|
2
go.mod
2
go.mod
|
@ -8,7 +8,6 @@ require (
|
|||
github.com/aybabtme/humanlog v0.4.1
|
||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
|
||||
github.com/creack/pty v1.1.11
|
||||
github.com/fsmiamoto/git-todo-parser v0.0.5
|
||||
github.com/gdamore/tcell/v2 v2.7.4
|
||||
github.com/go-errors/errors v1.5.1
|
||||
github.com/gookit/color v1.4.2
|
||||
|
@ -34,6 +33,7 @@ require (
|
|||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/spf13/afero v1.9.5
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
|
||||
github.com/stefanhaller/git-todo-parser v0.0.7-0.20240406123903-fd957137b6e2
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778
|
||||
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8
|
||||
|
|
4
go.sum
4
go.sum
|
@ -84,8 +84,6 @@ github.com/fatih/color v1.7.1-0.20180516100307-2d684516a886/go.mod h1:Zm6kSWBoL9
|
|||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsmiamoto/git-todo-parser v0.0.5 h1:Bhzd/vz/6Qm3udfkd6NO9fWfD3TpwR9ucp3N75/J5I8=
|
||||
github.com/fsmiamoto/git-todo-parser v0.0.5/go.mod h1:B+AgTbNE2BARvJqzXygThzqxLIaEWvwr2sxKYYb0Fas=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
|
||||
|
@ -281,6 +279,8 @@ github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
|
|||
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad h1:fiWzISvDn0Csy5H0iwgAuJGQTUpVfEMJJd4nRFXogbc=
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
||||
github.com/stefanhaller/git-todo-parser v0.0.7-0.20240406123903-fd957137b6e2 h1:RTNWemd/9z9A5L/AggEP3OdhRz5dXETB/wdAlYF0SuM=
|
||||
github.com/stefanhaller/git-todo-parser v0.0.7-0.20240406123903-fd957137b6e2/go.mod h1:HFt9hGqMzgQ+gVxMKcvTvGaFz4Y0yYycqqAp2V3wcJY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
|
|
|
@ -8,11 +8,11 @@ import (
|
|||
"os/exec"
|
||||
"strconv"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
// Sometimes lazygit will be invoked in daemon mode from a parent lazygit process.
|
||||
|
@ -33,6 +33,7 @@ const (
|
|||
DaemonKindUnknown DaemonKind = iota
|
||||
|
||||
DaemonKindExitImmediately
|
||||
DaemonKindRemoveUpdateRefsForCopiedBranch
|
||||
DaemonKindCherryPick
|
||||
DaemonKindMoveTodosUp
|
||||
DaemonKindMoveTodosDown
|
||||
|
@ -53,14 +54,15 @@ func getInstruction() Instruction {
|
|||
jsonData := os.Getenv(DaemonInstructionEnvKey)
|
||||
|
||||
mapping := map[DaemonKind]func(string) Instruction{
|
||||
DaemonKindExitImmediately: deserializeInstruction[*ExitImmediatelyInstruction],
|
||||
DaemonKindCherryPick: deserializeInstruction[*CherryPickCommitsInstruction],
|
||||
DaemonKindChangeTodoActions: deserializeInstruction[*ChangeTodoActionsInstruction],
|
||||
DaemonKindMoveFixupCommitDown: deserializeInstruction[*MoveFixupCommitDownInstruction],
|
||||
DaemonKindMoveTodosUp: deserializeInstruction[*MoveTodosUpInstruction],
|
||||
DaemonKindMoveTodosDown: deserializeInstruction[*MoveTodosDownInstruction],
|
||||
DaemonKindInsertBreak: deserializeInstruction[*InsertBreakInstruction],
|
||||
DaemonKindWriteRebaseTodo: deserializeInstruction[*WriteRebaseTodoInstruction],
|
||||
DaemonKindExitImmediately: deserializeInstruction[*ExitImmediatelyInstruction],
|
||||
DaemonKindRemoveUpdateRefsForCopiedBranch: deserializeInstruction[*RemoveUpdateRefsForCopiedBranchInstruction],
|
||||
DaemonKindCherryPick: deserializeInstruction[*CherryPickCommitsInstruction],
|
||||
DaemonKindChangeTodoActions: deserializeInstruction[*ChangeTodoActionsInstruction],
|
||||
DaemonKindMoveFixupCommitDown: deserializeInstruction[*MoveFixupCommitDownInstruction],
|
||||
DaemonKindMoveTodosUp: deserializeInstruction[*MoveTodosUpInstruction],
|
||||
DaemonKindMoveTodosDown: deserializeInstruction[*MoveTodosDownInstruction],
|
||||
DaemonKindInsertBreak: deserializeInstruction[*InsertBreakInstruction],
|
||||
DaemonKindWriteRebaseTodo: deserializeInstruction[*WriteRebaseTodoInstruction],
|
||||
}
|
||||
|
||||
return mapping[getDaemonKind()](jsonData)
|
||||
|
@ -157,6 +159,26 @@ func NewExitImmediatelyInstruction() Instruction {
|
|||
return &ExitImmediatelyInstruction{}
|
||||
}
|
||||
|
||||
type RemoveUpdateRefsForCopiedBranchInstruction struct{}
|
||||
|
||||
func (self *RemoveUpdateRefsForCopiedBranchInstruction) Kind() DaemonKind {
|
||||
return DaemonKindRemoveUpdateRefsForCopiedBranch
|
||||
}
|
||||
|
||||
func (self *RemoveUpdateRefsForCopiedBranchInstruction) SerializedInstructions() string {
|
||||
return serializeInstruction(self)
|
||||
}
|
||||
|
||||
func (self *RemoveUpdateRefsForCopiedBranchInstruction) run(common *common.Common) error {
|
||||
return handleInteractiveRebase(common, func(path string) error {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func NewRemoveUpdateRefsForCopiedBranchInstruction() Instruction {
|
||||
return &RemoveUpdateRefsForCopiedBranchInstruction{}
|
||||
}
|
||||
|
||||
type CherryPickCommitsInstruction struct {
|
||||
Todo string
|
||||
}
|
||||
|
|
|
@ -5,11 +5,12 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/env"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
type TodoLine struct {
|
||||
|
@ -44,6 +45,10 @@ func handleInteractiveRebase(common *common.Common, f func(path string) error) e
|
|||
path := os.Args[1]
|
||||
|
||||
if strings.HasSuffix(path, "git-rebase-todo") {
|
||||
err := utils.RemoveUpdateRefsForCopiedBranch(path, getCommentChar())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f(path)
|
||||
} else if strings.HasSuffix(path, filepath.Join(gitDir(), "COMMIT_EDITMSG")) { // TODO: test
|
||||
// if we are rebasing and squashing, we'll see a COMMIT_EDITMSG
|
||||
|
|
|
@ -11,13 +11,13 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
// context:
|
||||
|
|
|
@ -5,13 +5,13 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@ import (
|
|||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/app/daemon"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
type PatchCommands struct {
|
||||
|
|
|
@ -5,13 +5,13 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/app/daemon"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
type RebaseCommands struct {
|
||||
|
@ -233,7 +233,7 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
|
|||
if opts.instruction != nil {
|
||||
cmdObj.AddEnvVars(daemon.ToEnvVars(opts.instruction)...)
|
||||
} else {
|
||||
gitSequenceEditor = "true"
|
||||
cmdObj.AddEnvVars(daemon.ToEnvVars(daemon.NewRemoveUpdateRefsForCopiedBranchInstruction())...)
|
||||
}
|
||||
|
||||
cmdObj.AddEnvVars(
|
||||
|
|
|
@ -3,8 +3,8 @@ package models
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
// Special commit hash for empty tree object
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
|
@ -16,6 +15,7 @@ import (
|
|||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
// after selecting the 200th commit, we'll load in all the rest
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/generics/set"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
|
@ -19,6 +18,7 @@ import (
|
|||
"github.com/kyokomi/emoji/v2"
|
||||
"github.com/samber/lo"
|
||||
"github.com/sasha-s/go-deadlock"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
type pipeSetCacheKey struct {
|
||||
|
|
|
@ -6,12 +6,12 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/gookit/color"
|
||||
"github.com/jesseduffield/generics/set"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/xo/terminfo"
|
||||
)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
// loads the session state at the time that a custom command is invoked, for use
|
||||
|
|
68
pkg/integration/tests/branch/rebase_copied_branch.go
Normal file
68
pkg/integration/tests/branch/rebase_copied_branch.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package branch
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var RebaseCopiedBranch = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Make a copy of a branch, rebase it, check that the original branch is unaffected",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
GitVersion: AtLeast("2.38.0"),
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.AppState.GitLogShowGraph = "never"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
EmptyCommit("master 1").
|
||||
EmptyCommit("master 2").
|
||||
NewBranchFrom("branch1", "master^").
|
||||
EmptyCommit("branch 1").
|
||||
EmptyCommit("branch 2").
|
||||
NewBranch("branch2")
|
||||
|
||||
shell.SetConfig("rebase.updateRefs", "true")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Commits().Lines(
|
||||
Contains("CI * branch 2"),
|
||||
Contains("CI branch 1"),
|
||||
Contains("CI master 1"),
|
||||
)
|
||||
|
||||
t.Views().Branches().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("branch2").IsSelected(),
|
||||
Contains("branch1"),
|
||||
Contains("master"),
|
||||
).
|
||||
NavigateToLine(Contains("master")).
|
||||
Press(keys.Branches.RebaseBranch).
|
||||
Tap(func() {
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Rebase 'branch2' onto 'master'")).
|
||||
Select(Contains("Simple rebase")).
|
||||
Confirm()
|
||||
})
|
||||
|
||||
t.Views().Commits().Lines(
|
||||
Contains("CI branch 2"),
|
||||
Contains("CI branch 1"),
|
||||
Contains("CI master 2"),
|
||||
Contains("CI master 1"),
|
||||
)
|
||||
|
||||
t.Views().Branches().
|
||||
Focus().
|
||||
NavigateToLine(Contains("branch1")).
|
||||
PressPrimaryAction()
|
||||
|
||||
t.Views().Commits().Lines(
|
||||
Contains("CI branch 2"),
|
||||
Contains("CI branch 1"),
|
||||
Contains("CI master 1"),
|
||||
)
|
||||
},
|
||||
})
|
|
@ -0,0 +1,56 @@
|
|||
package interactive_rebase
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var DropCommitInCopiedBranchWithUpdateRef = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Drops a commit in a branch that is a copy of another branch, and verify that the other branch is left alone",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
GitVersion: AtLeast("2.38.0"),
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.AppState.GitLogShowGraph = "never"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
NewBranch("branch1").
|
||||
CreateNCommits(3).
|
||||
NewBranch("branch2")
|
||||
|
||||
shell.SetConfig("rebase.updateRefs", "true")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("CI * commit 03").IsSelected(),
|
||||
Contains("CI commit 02"),
|
||||
Contains("CI commit 01"),
|
||||
).
|
||||
NavigateToLine(Contains("commit 02")).
|
||||
Press(keys.Universal.Remove).
|
||||
Tap(func() {
|
||||
t.ExpectPopup().Confirmation().
|
||||
Title(Equals("Drop commit")).
|
||||
Content(Equals("Are you sure you want to drop the selected commit(s)?")).
|
||||
Confirm()
|
||||
}).
|
||||
Lines(
|
||||
Contains("CI commit 03"), // no start on this commit because branch1 is no longer pointing to it
|
||||
Contains("CI commit 01"),
|
||||
)
|
||||
|
||||
t.Views().Branches().
|
||||
Focus().
|
||||
NavigateToLine(Contains("branch1")).
|
||||
PressPrimaryAction()
|
||||
|
||||
t.Views().Commits().Lines(
|
||||
Contains("CI commit 03"),
|
||||
Contains("CI commit 02"),
|
||||
Contains("CI commit 01"),
|
||||
)
|
||||
},
|
||||
})
|
|
@ -0,0 +1,41 @@
|
|||
package interactive_rebase
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var InteractiveRebaseOfCopiedBranch = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Check that interactively rebasing a branch that is a copy of another branch doesn't affect the original branch",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
GitVersion: AtLeast("2.38.0"),
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
config.AppState.GitLogShowGraph = "never"
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
NewBranch("branch1").
|
||||
CreateNCommits(3).
|
||||
NewBranch("branch2")
|
||||
|
||||
shell.SetConfig("rebase.updateRefs", "true")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Commits().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("CI * commit 03"),
|
||||
Contains("CI commit 02"),
|
||||
Contains("CI commit 01"),
|
||||
).
|
||||
NavigateToLine(Contains("commit 01")).
|
||||
Press(keys.Universal.Edit).
|
||||
Lines(
|
||||
// No update-ref todo for branch1 here, even though command-line git would have added it
|
||||
Contains("pick").Contains("CI commit 03"),
|
||||
Contains("pick").Contains("CI commit 02"),
|
||||
Contains("CI <-- YOU ARE HERE --- commit 01"),
|
||||
)
|
||||
},
|
||||
})
|
|
@ -47,6 +47,7 @@ var tests = []*components.IntegrationTest{
|
|||
branch.RebaseAbortOnConflict,
|
||||
branch.RebaseAndDrop,
|
||||
branch.RebaseCancelOnConflict,
|
||||
branch.RebaseCopiedBranch,
|
||||
branch.RebaseDoesNotAutosquash,
|
||||
branch.RebaseFromMarkedBase,
|
||||
branch.RebaseToUpstream,
|
||||
|
@ -170,6 +171,7 @@ var tests = []*components.IntegrationTest{
|
|||
interactive_rebase.AmendNonHeadCommitDuringRebase,
|
||||
interactive_rebase.DeleteUpdateRefTodo,
|
||||
interactive_rebase.DontShowBranchHeadsForTodoItems,
|
||||
interactive_rebase.DropCommitInCopiedBranchWithUpdateRef,
|
||||
interactive_rebase.DropTodoCommitWithUpdateRef,
|
||||
interactive_rebase.DropWithCustomCommentChar,
|
||||
interactive_rebase.EditFirstCommit,
|
||||
|
@ -178,6 +180,7 @@ var tests = []*components.IntegrationTest{
|
|||
interactive_rebase.EditTheConflCommit,
|
||||
interactive_rebase.FixupFirstCommit,
|
||||
interactive_rebase.FixupSecondCommit,
|
||||
interactive_rebase.InteractiveRebaseOfCopiedBranch,
|
||||
interactive_rebase.MidRebaseRangeSelect,
|
||||
interactive_rebase.Move,
|
||||
interactive_rebase.MoveInRebase,
|
||||
|
|
|
@ -4,10 +4,11 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
type Todo struct {
|
||||
|
@ -262,6 +263,31 @@ func moveFixupCommitDown(todos []todo.Todo, originalHash string, fixupHash strin
|
|||
return newTodos, nil
|
||||
}
|
||||
|
||||
func RemoveUpdateRefsForCopiedBranch(fileName string, commentChar byte) error {
|
||||
todos, err := ReadRebaseTodoFile(fileName, commentChar)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Filter out comments
|
||||
todos = lo.Filter(todos, func(t todo.Todo, _ int) bool {
|
||||
return t.Command != todo.Comment
|
||||
})
|
||||
|
||||
// Delete any update-ref todos at the end of the todo list. These are not
|
||||
// part of a stack of branches, and so shouldn't be updated. This makes it
|
||||
// possible to create a copy of a branch and rebase the copy without
|
||||
// affecting the original branch.
|
||||
if _, i, found := lo.FindLastIndexOf(todos, func(t todo.Todo) bool {
|
||||
return t.Command != todo.UpdateRef
|
||||
}); found && i < len(todos)-1 {
|
||||
todos = slices.Delete(todos, i+1, len(todos))
|
||||
return WriteRebaseTodoFile(fileName, todos, commentChar)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// We render a todo in the commits view if it's a commit or if it's an
|
||||
// update-ref. We don't render label, reset, or comment lines.
|
||||
func isRenderedTodo(t todo.Todo) bool {
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ func parseLine(line string, commentChar byte) (Todo, error) {
|
|||
return todo, ErrUnexpectedCommand
|
||||
}
|
||||
|
||||
if todo.Command == Break {
|
||||
if todo.Command == Break || todo.Command == NoOp {
|
||||
return todo, nil
|
||||
}
|
||||
|
|
@ -23,7 +23,6 @@ func writeTodo(f io.Writer, todo Todo, commentChar byte) error {
|
|||
|
||||
switch todo.Command {
|
||||
case NoOp:
|
||||
return nil
|
||||
|
||||
case Comment:
|
||||
sb.WriteByte(commentChar)
|
6
vendor/modules.txt
vendored
6
vendor/modules.txt
vendored
|
@ -34,9 +34,6 @@ github.com/emirpasic/gods/utils
|
|||
# github.com/fatih/color v1.9.0
|
||||
## explicit; go 1.13
|
||||
github.com/fatih/color
|
||||
# github.com/fsmiamoto/git-todo-parser v0.0.5
|
||||
## explicit; go 1.13
|
||||
github.com/fsmiamoto/git-todo-parser/todo
|
||||
# github.com/gdamore/encoding v1.0.1
|
||||
## explicit; go 1.9
|
||||
github.com/gdamore/encoding
|
||||
|
@ -269,6 +266,9 @@ github.com/spf13/afero/mem
|
|||
# github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
|
||||
## explicit
|
||||
github.com/spkg/bom
|
||||
# github.com/stefanhaller/git-todo-parser v0.0.7-0.20240406123903-fd957137b6e2
|
||||
## explicit; go 1.13
|
||||
github.com/stefanhaller/git-todo-parser/todo
|
||||
# github.com/stretchr/testify v1.8.1
|
||||
## explicit; go 1.13
|
||||
github.com/stretchr/testify/assert
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue