@@ -20,7 +20,7 @@ type project struct {
2020 wd string
2121 isRepo bool
2222 root config.Root
23- baseRef string
23+ baseRev string
2424 normalizedRepo string
2525 stackManager * stack.Manager
2626
@@ -139,18 +139,6 @@ func (p *project) isDefaultBranch() bool {
139139 return branch == git .DefaultBranch
140140}
141141
142- // defaultBaseRef returns the baseRef for the current git environment.
143- func (p * project ) defaultBaseRef () string {
144- if p .isDefaultBranch () &&
145- p .remoteDefaultCommit () == p .headCommit () {
146- _ , err := p .git .wrapper .RevParse (defaultBranchBaseRef )
147- if err == nil {
148- return defaultBranchBaseRef
149- }
150- }
151- return p .defaultBranchRef ()
152- }
153-
154142// defaultLocalBaseRef returns the baseRef in case there's no remote setup.
155143func (p * project ) defaultLocalBaseRef () string {
156144 git := p .gitcfg ()
@@ -163,9 +151,58 @@ func (p *project) defaultLocalBaseRef() string {
163151 return git .DefaultBranch
164152}
165153
166- func (p project ) defaultBranchRef () string {
167- git := p .gitcfg ()
168- return git .DefaultRemote + "/" + git .DefaultBranch
154+ // selectChangeBase returns the revision used for change comparison based on the current Git state.
155+ func (p * project ) selectChangeBase () string {
156+ gitcfg := p .gitcfg ()
157+ gw := p .git .wrapper
158+
159+ // Try using remote default branch first
160+ defaultBranchRev , _ := gw .RevParse (gitcfg .DefaultRemote + "/" + gitcfg .DefaultBranch )
161+ if defaultBranchRev == "" {
162+ // Fall back to local default branch
163+ defaultBranchRev , _ = gw .RevParse (gitcfg .DefaultBranch )
164+
165+ if defaultBranchRev == "" {
166+ // There's no default branch available, so we can't look for a common parent with it.
167+ return defaultBranchBaseRef
168+ }
169+ }
170+
171+ branch , _ := gw .CurrentBranch ()
172+
173+ // Either we are on a branch or at a detached HEAD.
174+ if branch != "" {
175+ if branch == gitcfg .DefaultBranch {
176+ // We are at the tip of the default branch -> latest default commit.
177+ return defaultBranchBaseRef
178+ }
179+
180+ // Fallthrough to common parent if not on default branch
181+ } else {
182+ headRev , _ := gw .RevParse ("HEAD" )
183+ isDetachedDefaultBranchTip := headRev == defaultBranchRev
184+ if isDetachedDefaultBranchTip {
185+ // We are at the latest commit of the default branch.
186+ return defaultBranchBaseRef
187+ }
188+
189+ isDefaultBranchAncestor , _ := gw .IsFirstParentAncestor ("HEAD" , defaultBranchRev )
190+ if isDefaultBranchAncestor {
191+ // We are at an older commit of the default branch.
192+ return defaultBranchBaseRef
193+ }
194+
195+ // Fallthrough to common parent if not at commit of default branch
196+ }
197+
198+ commonParentWithDefaultBranch , _ := gw .FindNearestCommonParent (defaultBranchRev , "HEAD" )
199+ if commonParentWithDefaultBranch != "" {
200+ // We have a nearest common parent with the default branch. Similar to the historic merge base.
201+ return commonParentWithDefaultBranch
202+ }
203+
204+ // Fall back to default. Should never happen unless running on an isolated commit.
205+ return defaultBranchBaseRef
169206}
170207
171208func (p * project ) setDefaults () error {
0 commit comments