Log hashes of local branches when deleting them (#5441)

This makes it easier to recover them if they were deleted accidentally.

We only do this for local branches for now, we don't bother for remote
branches; it would be trickier there, because the branch on the server
might not actually point to the same hash as our local remote tracking
branch does.

Fixes #2468.
This commit is contained in:
Stefan Haller 2026-04-06 19:10:03 +02:00 committed by GitHub
commit 2057dc1ea9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 27 additions and 3 deletions

View file

@ -43,6 +43,7 @@ func (self *BranchesHelper) ConfirmLocalDelete(branches []*models.Branch) error
doDelete := func() error {
return self.c.WithWaitingStatus(self.c.Tr.DeletingStatus, func(_ gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.DeleteLocalBranch)
self.logBranchHashes(branches)
branchNames := lo.Map(branches, func(branch *models.Branch, _ int) string { return branch.Name })
if err := self.c.Git().Branch.LocalDelete(branchNames, true); err != nil {
return err
@ -178,6 +179,7 @@ func (self *BranchesHelper) ConfirmLocalAndRemoteDelete(branches []*models.Branc
}
self.c.LogAction(self.c.Tr.Actions.DeleteLocalBranch)
self.logBranchHashes(branches)
branchNames := lo.Map(branches, func(branch *models.Branch, _ int) string { return branch.Name })
if err := self.c.Git().Branch.LocalDelete(branchNames, true); err != nil {
return err
@ -257,6 +259,20 @@ func (self *BranchesHelper) allBranchesMerged(branches []*models.Branch) (bool,
return allBranchesMerged, nil
}
func (self *BranchesHelper) logBranchHashes(branches []*models.Branch) {
for _, branch := range branches {
msg := utils.ResolvePlaceholderString(
self.c.Tr.Log.DeletingBranch,
map[string]string{
"branchName": branch.Name,
"hash": branch.CommitHash,
},
)
self.c.LogCommand(msg, false)
}
}
func (self *BranchesHelper) deleteRemoteBranches(remoteBranches []*models.RemoteBranch, task gocui.Task) error {
remotes := lo.GroupBy(remoteBranches, func(branch *models.RemoteBranch) string { return branch.RemoteName })
for remote, branches := range remotes {

View file

@ -1,6 +1,8 @@
package controllers
import (
"fmt"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/style"
@ -129,7 +131,7 @@ func (self *StashController) handleStashApply(stashEntry *models.StashEntry) err
func (self *StashController) handleStashPop(stashEntry *models.StashEntry) error {
pop := func() error {
self.c.LogAction(self.c.Tr.Actions.PopStash)
self.c.LogCommand("Popping stash "+stashEntry.Hash, false)
self.c.LogCommand(fmt.Sprintf(self.c.Tr.Log.PoppingStash, stashEntry.Hash), false)
err := self.c.Git().Stash.Pop(stashEntry.Index)
self.postStashRefresh()
if err != nil {
@ -163,7 +165,7 @@ func (self *StashController) handleStashDrop(stashEntries []*models.StashEntry)
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.DropStash)
for i := len(stashEntries) - 1; i >= 0; i-- {
self.c.LogCommand("Dropping stash "+stashEntries[i].Hash, false)
self.c.LogCommand(fmt.Sprintf(self.c.Tr.Log.DroppingStash, stashEntries[i].Hash), false)
err := self.c.Git().Stash.Drop(stashEntries[i].Index)
self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.STASH}})
if err != nil {

View file

@ -963,6 +963,9 @@ type Log struct {
CreateFileWithContent string
AppendingLineToFile string
EditRebaseFromBaseCommit string
DroppingStash string
PoppingStash string
DeletingBranch string
}
type Actions struct {
@ -2196,7 +2199,10 @@ func EnglishTranslationSet() *TranslationSet {
Remove: "Removing '{{.filename}}'",
CreateFileWithContent: "Creating file '{{.path}}'",
AppendingLineToFile: "Appending '{{.line}}' to file '{{.filename}}'",
EditRebaseFromBaseCommit: "Beginning interactive rebase from '{{.baseCommit}}' onto '{{.targetBranchName}}",
EditRebaseFromBaseCommit: "Beginning interactive rebase from '{{.baseCommit}}' onto '{{.targetBranchName}}'",
DroppingStash: "Dropping stash %s",
PoppingStash: "Popping stash %s",
DeletingBranch: "Deleting branch '{{.branchName}}' (was {{.hash}})",
},
BreakingChangesTitle: "Breaking Changes",
BreakingChangesMessage: `You are updating to a new version of lazygit which contains breaking changes. Please review the notes below and update your configuration if necessary.