@@ -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
- fatal ("unable to git rev-parse" , err )
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
}
@@ -125,47 +110,58 @@ func (p *project) remoteDefaultCommit() string {
125
110
return p .git .remoteDefaultBranchCommit
126
111
}
127
112
128
- func (p * project ) isDefaultBranch () bool {
129
- git := p .gitcfg ()
130
- branch , err := p .git .wrapper .CurrentBranch ()
131
- if err != nil {
132
- // WHY?
133
- // The current branch name (the symbolic-ref of the HEAD) is not always
134
- // available, in this case we naively check if HEAD == local origin/main.
135
- // This case usually happens in the git setup of CIs.
136
- return p .localDefaultBranchCommit () == p .headCommit ()
137
- }
113
+ // selectChangeBase returns the revision used for change comparison based on the current Git state.
114
+ func (p * project ) selectChangeBase () string {
115
+ gitcfg := p .gitcfg ()
116
+ gw := p .git .wrapper
138
117
139
- return branch == git .DefaultBranch
140
- }
118
+ // Try using remote default branch first
119
+ defaultBranchRev , _ := gw .RevParse (gitcfg .DefaultRemote + "/" + gitcfg .DefaultBranch )
120
+ if defaultBranchRev == "" {
121
+ // Fall back to local default branch
122
+ defaultBranchRev , _ = gw .RevParse (gitcfg .DefaultBranch )
141
123
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 {
124
+ if defaultBranchRev == "" {
125
+ // There's no default branch available, so we can't look for a common parent with it.
148
126
return defaultBranchBaseRef
149
127
}
150
128
}
151
- return p .defaultBranchRef ()
152
- }
153
129
154
- // defaultLocalBaseRef returns the baseRef in case there's no remote setup.
155
- func (p * project ) defaultLocalBaseRef () string {
156
- git := p .gitcfg ()
157
- if p .isDefaultBranch () {
158
- _ , err := p .git .wrapper .RevParse (defaultBranchBaseRef )
159
- if err == nil {
130
+ branch , _ := gw .CurrentBranch ()
131
+
132
+ // Either we are on a branch or at a detached HEAD.
133
+ if branch != "" {
134
+ if branch == gitcfg .DefaultBranch {
135
+ // We are at the tip of the default branch -> latest default commit.
136
+ return defaultBranchBaseRef
137
+ }
138
+
139
+ // Fallthrough to common parent if not on default branch
140
+ } else {
141
+ headRev , _ := gw .RevParse ("HEAD" )
142
+ isDetachedDefaultBranchTip := headRev == defaultBranchRev
143
+ if isDetachedDefaultBranchTip {
144
+ // We are at the latest commit of the default branch.
160
145
return defaultBranchBaseRef
161
146
}
147
+
148
+ isDefaultBranchAncestor , _ := gw .IsFirstParentAncestor ("HEAD" , defaultBranchRev )
149
+ if isDefaultBranchAncestor {
150
+ // We are at an older commit of the default branch.
151
+ return defaultBranchBaseRef
152
+ }
153
+
154
+ // Fallthrough to common parent if not at commit of default branch
155
+ }
156
+
157
+ commonParentWithDefaultBranch , _ := gw .FindNearestCommonParent (defaultBranchRev , "HEAD" )
158
+ if commonParentWithDefaultBranch != "" {
159
+ // We have a nearest common parent with the default branch. Similar to the historic merge base.
160
+ return commonParentWithDefaultBranch
162
161
}
163
- return git .DefaultBranch
164
- }
165
162
166
- func (p project ) defaultBranchRef () string {
167
- git := p .gitcfg ()
168
- return git .DefaultRemote + "/" + git .DefaultBranch
163
+ // Fall back to default. Should never happen unless running on an isolated commit.
164
+ return defaultBranchBaseRef
169
165
}
170
166
171
167
func (p * project ) setDefaults () error {
0 commit comments