@@ -106,8 +106,23 @@ func Push(remote string, branches []string, force, atomic bool) error {
106106}
107107
108108// Rebase rebases the current branch onto the given base.
109+ // If rerere resolves all conflicts automatically, the rebase continues
110+ // without user intervention.
109111func Rebase (base string ) error {
110- return runSilent ("rebase" , base )
112+ err := runSilent ("rebase" , base )
113+ if err == nil {
114+ return nil
115+ }
116+ return tryAutoResolveRebase (err )
117+ }
118+
119+ // EnableRerere enables git rerere (reuse recorded resolution) and
120+ // rerere.autoupdate (auto-stage resolved files) for the repository.
121+ func EnableRerere () error {
122+ if err := runSilent ("config" , "rerere.enabled" , "true" ); err != nil {
123+ return err
124+ }
125+ return runSilent ("config" , "rerere.autoupdate" , "true" )
111126}
112127
113128// RebaseOnto rebases a branch using the three-argument form:
@@ -117,19 +132,59 @@ func Rebase(base string) error {
117132// This replays commits after oldBase from branch onto newBase. It is used
118133// when a prior branch was squash-merged and the normal rebase cannot detect
119134// which commits have already been applied.
135+ // If rerere resolves all conflicts automatically, the rebase continues
136+ // without user intervention.
120137func RebaseOnto (newBase , oldBase , branch string ) error {
121- return runSilent ("rebase" , "--onto" , newBase , oldBase , branch )
138+ err := runSilent ("rebase" , "--onto" , newBase , oldBase , branch )
139+ if err == nil {
140+ return nil
141+ }
142+ return tryAutoResolveRebase (err )
122143}
123144
124145// RebaseContinue continues an in-progress rebase.
125146// It sets GIT_EDITOR=true to prevent git from opening an interactive editor
126147// for the commit message, which would cause the command to hang.
148+ // If rerere resolves subsequent conflicts automatically, the rebase continues
149+ // without user intervention.
127150func RebaseContinue () error {
151+ err := rebaseContinueOnce ()
152+ if err == nil {
153+ return nil
154+ }
155+ return tryAutoResolveRebase (err )
156+ }
157+
158+ // rebaseContinueOnce runs a single git rebase --continue without auto-resolve.
159+ func rebaseContinueOnce () error {
128160 cmd := exec .Command ("git" , "rebase" , "--continue" )
129161 cmd .Env = append (os .Environ (), "GIT_EDITOR=true" )
130162 return cmd .Run ()
131163}
132164
165+ // tryAutoResolveRebase checks whether rerere has resolved all conflicts
166+ // from a failed rebase. If so, it auto-continues the rebase (potentially
167+ // multiple times for multi-commit rebases). Returns originalErr if any
168+ // conflicts remain that need manual resolution.
169+ func tryAutoResolveRebase (originalErr error ) error {
170+ for i := 0 ; i < 1000 ; i ++ {
171+ if ! IsRebaseInProgress () {
172+ return nil
173+ }
174+ conflicts , _ := ConflictedFiles ()
175+ if len (conflicts ) > 0 {
176+ return originalErr
177+ }
178+ // Rerere resolved all conflicts — auto-continue.
179+ if rebaseContinueOnce () == nil {
180+ return nil
181+ }
182+ // Continue hit another conflicting commit; loop to check
183+ // if rerere resolved that one too.
184+ }
185+ return originalErr
186+ }
187+
133188// RebaseAbort aborts an in-progress rebase.
134189func RebaseAbort () error {
135190 return runSilent ("rebase" , "--abort" )
0 commit comments