@@ -99,6 +99,16 @@ func applyChangesToTree(repo *git.Repository, baseTreeHash plumbing.Hash, change
9999 Hash : newSubHash ,
100100 })
101101 processedDirs [entry .Name ] = true
102+ } else if fileChange , ok := changes .files [entry .Name ]; ok {
103+ // Type conflict: base has dir, changes has file → replace dir with file
104+ if ! fileChange .delete {
105+ newEntries = append (newEntries , object.TreeEntry {
106+ Name : entry .Name ,
107+ Mode : fileChange .mode ,
108+ Hash : fileChange .hash ,
109+ })
110+ }
111+ processedFiles [entry .Name ] = true
102112 } else {
103113 // No changes in this directory, keep as-is
104114 newEntries = append (newEntries , entry )
@@ -115,6 +125,20 @@ func applyChangesToTree(repo *git.Repository, baseTreeHash plumbing.Hash, change
115125 }
116126 // If delete: don't add to newEntries
117127 processedFiles [entry .Name ] = true
128+ } else if dirChanges , ok := changes .dirs [entry .Name ]; ok {
129+ // Type conflict: base has file, changes has dir → replace file with dir
130+ newSubHash , subErr := createTreeFromChanges (repo , dirChanges )
131+ if subErr != nil {
132+ return plumbing .ZeroHash , subErr
133+ }
134+ if newSubHash != plumbing .ZeroHash {
135+ newEntries = append (newEntries , object.TreeEntry {
136+ Name : entry .Name ,
137+ Mode : filemode .Dir ,
138+ Hash : newSubHash ,
139+ })
140+ }
141+ processedDirs [entry .Name ] = true
118142 } else {
119143 // No change, keep as-is
120144 newEntries = append (newEntries , entry )
@@ -140,6 +164,10 @@ func applyChangesToTree(repo *git.Repository, baseTreeHash plumbing.Hash, change
140164 if subErr != nil {
141165 return plumbing .ZeroHash , subErr
142166 }
167+ // Skip empty trees (e.g., all changes were deletions for non-existent paths)
168+ if newSubHash == plumbing .ZeroHash {
169+ continue
170+ }
143171 newEntries = append (newEntries , object.TreeEntry {
144172 Name : name ,
145173 Mode : filemode .Dir ,
@@ -172,13 +200,22 @@ func createTreeFromChanges(repo *git.Repository, changes *changeTree) (plumbing.
172200 if err != nil {
173201 return plumbing .ZeroHash , err
174202 }
203+ // Skip empty subtrees (all files were deletions)
204+ if subHash == plumbing .ZeroHash {
205+ continue
206+ }
175207 entries = append (entries , object.TreeEntry {
176208 Name : name ,
177209 Mode : filemode .Dir ,
178210 Hash : subHash ,
179211 })
180212 }
181213
214+ // If all entries were deletions, don't create an empty tree
215+ if len (entries ) == 0 {
216+ return plumbing .ZeroHash , nil
217+ }
218+
182219 sortTreeEntries (entries )
183220 return storeTree (repo , entries )
184221}
@@ -219,7 +256,7 @@ func addDirectoryToChangeTree(repo *git.Repository, dirPathAbs, dirPathRel strin
219256 }
220257
221258 // Use forward slashes for git tree paths
222- treePath := dirPathRel + "/" + filepath .ToSlash (relWithinDir )
259+ treePath := filepath . ToSlash ( dirPathRel ) + "/" + filepath .ToSlash (relWithinDir )
223260 ct .addFile (treePath , blobHash , mode )
224261 return nil
225262 })
0 commit comments