From c4f43d34cba653ae0249aa3dd0a29c08e812dfe8 Mon Sep 17 00:00:00 2001 From: Guillem Poy Date: Thu, 5 Mar 2026 16:58:29 +0100 Subject: [PATCH 1/4] Add optional branch name display in repository list Add a preference toggle (disabled by default) in the Appearance tab under "Repository list" to show the current branch name next to each repository name in the sidebar. The branch name appears with a git-branch icon in a secondary color with ellipsis for overflow. Resolves desktop/desktop#8158 Co-Authored-By: Claude Opus 4.6 --- app/src/lib/app-state.ts | 3 +++ app/src/lib/stores/app-store.ts | 26 +++++++++++++++++-- app/src/models/repository.ts | 5 ++++ app/src/ui/app.tsx | 2 ++ app/src/ui/dispatcher/dispatcher.ts | 6 +++++ app/src/ui/preferences/appearance.tsx | 17 ++++++++++++ app/src/ui/preferences/preferences.tsx | 15 +++++++++++ .../repositories-list/group-repositories.ts | 2 ++ .../repositories-list/repositories-list.tsx | 15 +++++++++++ .../repository-list-item.tsx | 16 +++++++++++- app/styles/ui/_repository-list.scss | 15 +++++++++++ 11 files changed, 119 insertions(+), 3 deletions(-) diff --git a/app/src/lib/app-state.ts b/app/src/lib/app-state.ts index 48a2e4ee32f..5fd75226d90 100644 --- a/app/src/lib/app-state.ts +++ b/app/src/lib/app-state.ts @@ -394,6 +394,9 @@ export interface IAppState { /** Whether or not the user will see check marks indicating a line is included in the check in the diff */ readonly showDiffCheckMarks: boolean + /** Whether or not to show the current branch name next to each repository in the repository list */ + readonly showBranchNameInRepoList: boolean + /** * Cached repo rulesets. Used to prevent repeatedly querying the same * rulesets to check their bypass status. diff --git a/app/src/lib/stores/app-store.ts b/app/src/lib/stores/app-store.ts index ed2ceeeab5c..549edb2aafe 100644 --- a/app/src/lib/stores/app-store.ts +++ b/app/src/lib/stores/app-store.ts @@ -480,6 +480,9 @@ export const underlineLinksDefault = true export const showDiffCheckMarksDefault = true export const showDiffCheckMarksKey = 'diff-check-marks-visible' +export const showBranchNameInRepoListDefault = false +export const showBranchNameInRepoListKey = 'show-branch-name-in-repo-list' + const commitMessageGenerationDisclaimerLastSeenKey = 'commit-message-generation-disclaimer-last-seen' @@ -645,6 +648,8 @@ export class AppStore extends TypedBaseStore { private showDiffCheckMarks: boolean = showDiffCheckMarksDefault + private showBranchNameInRepoList: boolean = showBranchNameInRepoListDefault + private cachedRepoRulesets = new Map() private underlineLinks: boolean = underlineLinksDefault @@ -1192,6 +1197,7 @@ export class AppStore extends TypedBaseStore { cachedRepoRulesets: this.cachedRepoRulesets, underlineLinks: this.underlineLinks, showDiffCheckMarks: this.showDiffCheckMarks, + showBranchNameInRepoList: this.showBranchNameInRepoList, updateState: updateStore.state, commitMessageGenerationDisclaimerLastSeen: this.commitMessageGenerationDisclaimerLastSeen, @@ -2595,6 +2601,11 @@ export class AppStore extends TypedBaseStore { showDiffCheckMarksDefault ) + this.showBranchNameInRepoList = getBoolean( + showBranchNameInRepoListKey, + showBranchNameInRepoListDefault + ) + this.commitMessageGenerationDisclaimerLastSeen = getNumber(commitMessageGenerationDisclaimerLastSeenKey) ?? null @@ -3984,6 +3995,7 @@ export class AppStore extends TypedBaseStore { lookup.set(repository.id, { aheadBehind: status.branchAheadBehind || null, changedFilesCount: status.workingDirectory.files.length, + branchName: status.currentBranch, }) } /** @@ -4025,9 +4037,11 @@ export class AppStore extends TypedBaseStore { const existing = lookup.get(repository.id) lookup.set(repository.id, { aheadBehind: aheadBehind, - // We don't need to update changedFilesCount here since it was already - // set when calling `updateSidebarIndicator()` with the status object. + // We don't need to update changedFilesCount or branchName here since + // they were already set when calling `updateSidebarIndicator()` with + // the status object. changedFilesCount: existing?.changedFilesCount ?? 0, + branchName: existing?.branchName, }) this.emitUpdate() } @@ -9113,6 +9127,14 @@ export class AppStore extends TypedBaseStore { } } + public _updateShowBranchNameInRepoList(showBranchNameInRepoList: boolean) { + if (showBranchNameInRepoList !== this.showBranchNameInRepoList) { + this.showBranchNameInRepoList = showBranchNameInRepoList + setBoolean(showBranchNameInRepoListKey, showBranchNameInRepoList) + this.emitUpdate() + } + } + public _updateFileListFilter( repository: Repository, filterUpdate: Partial diff --git a/app/src/models/repository.ts b/app/src/models/repository.ts index 2899925701f..d04e0de8b2f 100644 --- a/app/src/models/repository.ts +++ b/app/src/models/repository.ts @@ -220,6 +220,11 @@ export interface ILocalRepositoryState { * The number of uncommitted changes currently in the repository. */ readonly changedFilesCount: number + /** + * The name of the currently checked out branch, or `undefined` if the + * branch name is not available (e.g. detached HEAD). + */ + readonly branchName?: string } /** diff --git a/app/src/ui/app.tsx b/app/src/ui/app.tsx index da5c21bcfbd..afe29c39354 100644 --- a/app/src/ui/app.tsx +++ b/app/src/ui/app.tsx @@ -1644,6 +1644,7 @@ export class App extends React.Component { onEditGlobalGitConfig={this.editGlobalGitConfig} underlineLinks={this.state.underlineLinks} showDiffCheckMarks={this.state.showDiffCheckMarks} + showBranchNameInRepoList={this.state.showBranchNameInRepoList} /> ) case PopupType.RepositorySettings: { @@ -3027,6 +3028,7 @@ export class App extends React.Component { externalEditorLabel={this.externalEditorLabel} shellLabel={useCustomShell ? undefined : selectedShell} dispatcher={this.props.dispatcher} + showBranchNameInRepoList={this.state.showBranchNameInRepoList} /> ) } diff --git a/app/src/ui/dispatcher/dispatcher.ts b/app/src/ui/dispatcher/dispatcher.ts index f85ff7ebb00..e73a33630b0 100644 --- a/app/src/ui/dispatcher/dispatcher.ts +++ b/app/src/ui/dispatcher/dispatcher.ts @@ -4191,6 +4191,12 @@ export class Dispatcher { return this.appStore._updateShowDiffCheckMarks(diffCheckMarks) } + public setShowBranchNameInRepoList(showBranchNameInRepoList: boolean) { + return this.appStore._updateShowBranchNameInRepoList( + showBranchNameInRepoList + ) + } + public testPruneBranches() { return this.appStore._testPruneBranches() } diff --git a/app/src/ui/preferences/appearance.tsx b/app/src/ui/preferences/appearance.tsx index dff3f590fad..5c1be7f9691 100644 --- a/app/src/ui/preferences/appearance.tsx +++ b/app/src/ui/preferences/appearance.tsx @@ -24,6 +24,8 @@ interface IAppearanceProps { readonly onShowRecentRepositoriesChanged: (show: boolean) => void readonly showWorktrees: boolean readonly onShowWorktreesChanged: (show: boolean) => void + readonly showBranchNameInRepoList: boolean + readonly onShowBranchNameInRepoListChanged: (value: boolean) => void } interface IAppearanceState { @@ -213,6 +215,12 @@ export class Appearance extends React.Component< ) } + private onShowBranchNameInRepoListChanged = ( + event: React.FormEvent + ) => { + this.props.onShowBranchNameInRepoListChanged(event.currentTarget.checked) + } + private renderRepositoryList() { return (
@@ -227,6 +235,15 @@ export class Appearance extends React.Component< } onChange={this.onShowRecentRepositoriesChanged} /> +
) } diff --git a/app/src/ui/preferences/preferences.tsx b/app/src/ui/preferences/preferences.tsx index 29ff91ad63a..14bf6157807 100644 --- a/app/src/ui/preferences/preferences.tsx +++ b/app/src/ui/preferences/preferences.tsx @@ -93,6 +93,7 @@ interface IPreferencesProps { readonly showRecentRepositories: boolean readonly showWorktrees: boolean readonly repositoryIndicatorsEnabled: boolean + readonly showBranchNameInRepoList: boolean readonly hideWindowOnQuit: boolean readonly onEditGlobalGitConfig: () => void readonly underlineLinks: boolean @@ -144,6 +145,7 @@ interface IPreferencesState { */ readonly existingLockFilePath?: string readonly repositoryIndicatorsEnabled: boolean + readonly showBranchNameInRepoList: boolean readonly hideWindowOnQuit: boolean readonly initiallySelectedTheme: ApplicationTheme @@ -219,6 +221,7 @@ export class Preferences extends React.Component< showRecentRepositories: this.props.showRecentRepositories, showWorktrees: this.props.showWorktrees, repositoryIndicatorsEnabled: this.props.repositoryIndicatorsEnabled, + showBranchNameInRepoList: this.props.showBranchNameInRepoList, hideWindowOnQuit: this.props.hideWindowOnQuit, initiallySelectedTheme: this.props.selectedTheme, initiallySelectedTabSize: this.props.selectedTabSize, @@ -552,6 +555,10 @@ export class Preferences extends React.Component< } showWorktrees={this.state.showWorktrees} onShowWorktreesChanged={this.onShowWorktreesChanged} + showBranchNameInRepoList={this.state.showBranchNameInRepoList} + onShowBranchNameInRepoListChanged={ + this.onShowBranchNameInRepoListChanged + } /> ) break @@ -797,6 +804,12 @@ export class Preferences extends React.Component< this.setState({ showDiffCheckMarks }) } + private onShowBranchNameInRepoListChanged = ( + showBranchNameInRepoList: boolean + ) => { + this.setState({ showBranchNameInRepoList }) + } + private onSelectedTabSizeChanged = (tabSize: number) => { this.props.dispatcher.setSelectedTabSize(tabSize) } @@ -1002,6 +1015,8 @@ export class Preferences extends React.Component< dispatcher.setDiffCheckMarksSetting(this.state.showDiffCheckMarks) + dispatcher.setShowBranchNameInRepoList(this.state.showBranchNameInRepoList) + this.props.onDismissed() } diff --git a/app/src/ui/repositories-list/group-repositories.ts b/app/src/ui/repositories-list/group-repositories.ts index 6dc7bfe2915..757f91b7f89 100644 --- a/app/src/ui/repositories-list/group-repositories.ts +++ b/app/src/ui/repositories-list/group-repositories.ts @@ -61,6 +61,7 @@ export interface IRepositoryListItem extends IFilterListItem { readonly needsDisambiguation: boolean readonly aheadBehind: IAheadBehind | null readonly changedFilesCount: number + readonly branchName?: string } const recentRepositoriesThreshold = 7 @@ -182,6 +183,7 @@ const toSortedListItems = ( ((allNames.get(title) ?? 0) > 1 && group.kind === 'recent'), aheadBehind: repoState?.aheadBehind ?? null, changedFilesCount: repoState?.changedFilesCount ?? 0, + branchName: repoState?.branchName, } }) .sort(({ repository: x }, { repository: y }) => diff --git a/app/src/ui/repositories-list/repositories-list.tsx b/app/src/ui/repositories-list/repositories-list.tsx index 9a5f1624e6b..038a9aa47b6 100644 --- a/app/src/ui/repositories-list/repositories-list.tsx +++ b/app/src/ui/repositories-list/repositories-list.tsx @@ -75,6 +75,9 @@ interface IRepositoriesListProps { readonly filterText: string readonly dispatcher: Dispatcher + + /** Whether to show the branch name next to each repository */ + readonly showBranchNameInRepoList: boolean } interface IRepositoriesListState { @@ -165,6 +168,9 @@ export class RepositoriesList extends React.Component< matches={matches} aheadBehind={item.aheadBehind} changedFilesCount={item.changedFilesCount} + branchName={ + this.props.showBranchNameInRepoList ? item.branchName : undefined + } /> ) } @@ -193,6 +199,9 @@ export class RepositoriesList extends React.Component< item: IRepositoryListItem ): JSX.Element | string | null => { const { repository, aheadBehind, changedFilesCount } = item + const branchName = this.props.showBranchNameInRepoList + ? item.branchName + : undefined const gitHubRepo = repository instanceof Repository ? repository.gitHubRepository : null const alias = repository instanceof Repository ? repository.alias : null @@ -217,6 +226,12 @@ export class RepositoriesList extends React.Component<
Path:
{repository.path} + {branchName && ( +
+
Branch:
+ {branchName} +
+ )} {aheadBehindTooltip && (
diff --git a/app/src/ui/repositories-list/repository-list-item.tsx b/app/src/ui/repositories-list/repository-list-item.tsx index 54cbe675bbc..8535bf9cd43 100644 --- a/app/src/ui/repositories-list/repository-list-item.tsx +++ b/app/src/ui/repositories-list/repository-list-item.tsx @@ -27,6 +27,9 @@ interface IRepositoryListItemProps { /** Number of uncommitted changes */ readonly changedFilesCount: number + + /** The name of the current branch, if available */ + readonly branchName?: string } /** A repository item. */ @@ -74,6 +77,15 @@ export class RepositoryListItem extends React.Component< text={alias ?? repository.name} highlight={this.props.matches.title} /> + {this.props.branchName && ( + + + {this.props.branchName} + + )}
{repository instanceof Repository && @@ -98,6 +110,7 @@ export class RepositoryListItem extends React.Component< {alias && <> ({alias})}
{repo.path}
+ {this.props.branchName &&
Branch: {this.props.branchName}
} ) } @@ -109,7 +122,8 @@ export class RepositoryListItem extends React.Component< ) { return ( nextProps.repository.id !== this.props.repository.id || - nextProps.matches !== this.props.matches + nextProps.matches !== this.props.matches || + nextProps.branchName !== this.props.branchName ) } else { return true diff --git a/app/styles/ui/_repository-list.scss b/app/styles/ui/_repository-list.scss index 3b509b81165..a51b1b4c61b 100644 --- a/app/styles/ui/_repository-list.scss +++ b/app/styles/ui/_repository-list.scss @@ -65,6 +65,21 @@ .alias { font-style: italic; } + + .branch-name { + color: var(--text-secondary-color); + font-size: var(--font-size-sm); + margin-left: var(--spacing-half); + @include ellipsis; + flex-shrink: 1; + + .branch-icon { + height: 12px; + width: 12px; + margin-right: 2px; + vertical-align: text-bottom; + } + } } .filter-list-group-header { From c4a213dd36ca4b1ae40acc2ff12af8ac9f224fff Mon Sep 17 00:00:00 2001 From: Guillem Poy Date: Thu, 5 Mar 2026 18:00:33 +0100 Subject: [PATCH 2/4] Fix prettier formatting in repository-list-item.tsx Co-Authored-By: Claude Opus 4.6 --- app/src/ui/repositories-list/repository-list-item.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/ui/repositories-list/repository-list-item.tsx b/app/src/ui/repositories-list/repository-list-item.tsx index 8535bf9cd43..b99e9271eb9 100644 --- a/app/src/ui/repositories-list/repository-list-item.tsx +++ b/app/src/ui/repositories-list/repository-list-item.tsx @@ -79,10 +79,7 @@ export class RepositoryListItem extends React.Component< /> {this.props.branchName && ( - + {this.props.branchName} )} From 2f418bfe990477002e3a31031cdb13fcfc20ce5a Mon Sep 17 00:00:00 2001 From: Guillem Poy Date: Fri, 6 Mar 2026 09:46:21 +0100 Subject: [PATCH 3/4] Style branch name as a subtle pill badge in repository list Add a rounded pill background to the branch name indicator using a new --branch-pill-background-color CSS variable. The pill adapts to light/dark themes and selected/focused list item states, matching the existing badge styling conventions. Co-Authored-By: Claude Opus 4.6 --- app/styles/_variables.scss | 1 + app/styles/themes/_dark.scss | 1 + app/styles/ui/_repository-list.scss | 19 ++++++++++++++----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/app/styles/_variables.scss b/app/styles/_variables.scss index f25bfe3f886..db530e6479b 100644 --- a/app/styles/_variables.scss +++ b/app/styles/_variables.scss @@ -338,6 +338,7 @@ $overlay-background-color: rgba(0, 0, 0, 0.4); */ --list-item-badge-color: #{$gray-800}; --list-item-badge-background-color: #{$gray-200}; + --branch-pill-background-color: #{$gray-100}; --list-item-selected-badge-color: #{$gray-900}; --list-item-selected-badge-background-color: #{$gray-300}; --list-item-selected-active-badge-color: #{$gray-900}; diff --git a/app/styles/themes/_dark.scss b/app/styles/themes/_dark.scss index aa31c752649..6a7c9b46a97 100644 --- a/app/styles/themes/_dark.scss +++ b/app/styles/themes/_dark.scss @@ -265,6 +265,7 @@ body.theme-dark { */ --list-item-badge-color: var(--text-color); --list-item-badge-background-color: #{$gray-600}; + --branch-pill-background-color: #{$gray-800}; --list-item-selected-badge-color: #{$white}; --list-item-selected-badge-background-color: #{$gray-500}; --list-item-selected-active-badge-color: #{$gray-900}; diff --git a/app/styles/ui/_repository-list.scss b/app/styles/ui/_repository-list.scss index a51b1b4c61b..5d45f8b938d 100644 --- a/app/styles/ui/_repository-list.scss +++ b/app/styles/ui/_repository-list.scss @@ -48,6 +48,8 @@ .name { // Long repository names truncate and ellipse @include ellipsis; + flex-shrink: 1; + min-width: 0; .prefix { color: var(--text-secondary-color); @@ -67,11 +69,16 @@ } .branch-name { - color: var(--text-secondary-color); + color: var(--list-item-badge-color); + background: var(--branch-pill-background-color); font-size: var(--font-size-sm); margin-left: var(--spacing-half); + padding: 0 var(--spacing-half); + border-radius: var(--border-radius); @include ellipsis; flex-shrink: 1; + min-width: 0; + line-height: 1.6; .branch-icon { height: 12px; @@ -148,11 +155,12 @@ } .list-focus-container { - /** Ahead/behind badge colors when list item is selected but not focused */ + /** Badge colors when list item is selected but not focused */ .list-item.selected { .repository-list-item, .repository-list-item-tooltip { - .ahead-behind { + .ahead-behind, + .branch-name { background: var(--list-item-selected-badge-background-color); color: var(--list-item-selected-badge-color); } @@ -160,11 +168,12 @@ } &.focus-within { - /** Ahead/behind badge colors when list item is selected and focused */ + /** Badge colors when list item is selected and focused */ .list-item.selected { .repository-list-item, .repository-list-item-tooltip { - .ahead-behind { + .ahead-behind, + .branch-name { background: var(--list-item-selected-active-badge-background-color); color: var(--list-item-selected-active-badge-color); } From 7f465ce6ccb2153811805b54b11943138f621997 Mon Sep 17 00:00:00 2001 From: Guillem Poy Date: Fri, 6 Mar 2026 09:46:30 +0100 Subject: [PATCH 4/4] Move branch pill outside .name container for proper truncation The branch-name element was nested inside the .name div which has overflow:hidden, causing the pill's rounded corners to be clipped with a straight edge when text overflows. Moving it to a sibling flex item preserves the pill's border-radius during truncation. Co-Authored-By: Claude Opus 4.6 --- .../ui/repositories-list/repository-list-item.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/ui/repositories-list/repository-list-item.tsx b/app/src/ui/repositories-list/repository-list-item.tsx index b99e9271eb9..19a17c3bbba 100644 --- a/app/src/ui/repositories-list/repository-list-item.tsx +++ b/app/src/ui/repositories-list/repository-list-item.tsx @@ -77,14 +77,15 @@ export class RepositoryListItem extends React.Component< text={alias ?? repository.name} highlight={this.props.matches.title} /> - {this.props.branchName && ( - - - {this.props.branchName} - - )} + {this.props.branchName && ( + + + {this.props.branchName} + + )} + {repository instanceof Repository && renderRepoIndicators({ aheadBehind: this.props.aheadBehind,