@@ -20,7 +20,7 @@ type project struct {
20
20
wd string
21
21
isRepo bool
22
22
root config.Root
23
- baseRef string
23
+ baseRev string
24
24
normalizedRepo string
25
25
stackManager * stack.Manager
26
26
@@ -63,21 +63,6 @@ func (p *project) prettyRepo() string {
63
63
return p .normalizedRepo
64
64
}
65
65
66
- func (p * project ) localDefaultBranchCommit () string {
67
- if p .git .localDefaultBranchCommit != "" {
68
- return p .git .localDefaultBranchCommit
69
- }
70
- gitcfg := p .gitcfg ()
71
- refName := gitcfg .DefaultRemote + "/" + gitcfg .DefaultBranch
72
- val , err := p .git .wrapper .RevParse (refName )
73
- if err != nil {
74
- fatalWithDetails (err , "unable to git rev-parse" )
75
- }
76
-
77
- p .git .localDefaultBranchCommit = val
78
- return val
79
- }
80
-
81
66
func (p * project ) isGitFeaturesEnabled () bool {
82
67
return p .isRepo && p .hasCommit ()
83
68
}
@@ -126,47 +111,58 @@ func (p *project) remoteDefaultCommit() string {
126
111
return p .git .remoteDefaultBranchCommit
127
112
}
128
113
129
- func (p * project ) isDefaultBranch () bool {
130
- git := p .gitcfg ()
131
- branch , err := p .git .wrapper .CurrentBranch ()
132
- if err != nil {
133
- // WHY?
134
- // The current branch name (the symbolic-ref of the HEAD) is not always
135
- // available, in this case we naively check if HEAD == local origin/main.
136
- // This case usually happens in the git setup of CIs.
137
- return p .localDefaultBranchCommit () == p .headCommit ()
138
- }
114
+ // selectChangeBase returns the revision used for change comparison based on the current Git state.
115
+ func (p * project ) selectChangeBase () string {
116
+ gitcfg := p .gitcfg ()
117
+ gw := p .git .wrapper
139
118
140
- return branch == git .DefaultBranch
141
- }
119
+ // Try using remote default branch first
120
+ defaultBranchRev , _ := gw .RevParse (gitcfg .DefaultRemote + "/" + gitcfg .DefaultBranch )
121
+ if defaultBranchRev == "" {
122
+ // Fall back to local default branch
123
+ defaultBranchRev , _ = gw .RevParse (gitcfg .DefaultBranch )
142
124
143
- // defaultBaseRef returns the baseRef for the current git environment.
144
- func (p * project ) defaultBaseRef () string {
145
- if p .isDefaultBranch () &&
146
- p .remoteDefaultCommit () == p .headCommit () {
147
- _ , err := p .git .wrapper .RevParse (defaultBranchBaseRef )
148
- if err == nil {
125
+ if defaultBranchRev == "" {
126
+ // There's no default branch available, so we can't look for a common parent with it.
149
127
return defaultBranchBaseRef
150
128
}
151
129
}
152
- return p .defaultBranchRef ()
153
- }
154
130
155
- // defaultLocalBaseRef returns the baseRef in case there's no remote setup.
156
- func (p * project ) defaultLocalBaseRef () string {
157
- git := p .gitcfg ()
158
- if p .isDefaultBranch () {
159
- _ , err := p .git .wrapper .RevParse (defaultBranchBaseRef )
160
- if err == nil {
131
+ branch , _ := gw .CurrentBranch ()
132
+
133
+ // Either we are on a branch or at a detached HEAD.
134
+ if branch != "" {
135
+ if branch == gitcfg .DefaultBranch {
136
+ // We are at the tip of the default branch -> latest default commit.
137
+ return defaultBranchBaseRef
138
+ }
139
+
140
+ // Fallthrough to common parent if not on default branch
141
+ } else {
142
+ headRev , _ := gw .RevParse ("HEAD" )
143
+ isDetachedDefaultBranchTip := headRev == defaultBranchRev
144
+ if isDetachedDefaultBranchTip {
145
+ // We are at the latest commit of the default branch.
161
146
return defaultBranchBaseRef
162
147
}
148
+
149
+ isDefaultBranchAncestor , _ := gw .IsFirstParentAncestor ("HEAD" , defaultBranchRev )
150
+ if isDefaultBranchAncestor {
151
+ // We are at an older commit of the default branch.
152
+ return defaultBranchBaseRef
153
+ }
154
+
155
+ // Fallthrough to common parent if not at commit of default branch
156
+ }
157
+
158
+ commonParentWithDefaultBranch , _ := gw .FindNearestCommonParent (defaultBranchRev , "HEAD" )
159
+ if commonParentWithDefaultBranch != "" {
160
+ // We have a nearest common parent with the default branch. Similar to the historic merge base.
161
+ return commonParentWithDefaultBranch
163
162
}
164
- return git .DefaultBranch
165
- }
166
163
167
- func (p project ) defaultBranchRef () string {
168
- git := p .gitcfg ()
169
- return git .DefaultRemote + "/" + git .DefaultBranch
164
+ // Fall back to default. Should never happen unless running on an isolated commit.
165
+ return defaultBranchBaseRef
170
166
}
171
167
172
168
func (p * project ) setDefaults () error {
0 commit comments