]> source.dussan.org Git - jgit.git/commitdiff
Make sure to overwrite files when "reset --hard" detects conflicts 99/57799/6
authorChristian Halstrick <christian.halstrick@sap.com>
Fri, 9 Oct 2015 14:14:10 +0000 (16:14 +0200)
committerMatthias Sohn <matthias.sohn@sap.com>
Wed, 18 May 2016 11:29:02 +0000 (13:29 +0200)
When performing a "reset --hard" a checkout is done. The pathes are
checked for potential checkout conflicts. But in the end for all
remaining conflicts these files are simply deleted from the working
tree. That's not the right strategy to handle checkout conflicts during
"reset --hard". Instead for every conflict we should simply checkout the
merge commit's content.

This is different from native gits behavior which reports errors when
during a "checkout --hard" a file shows up where a folder was expected.

  "warning: unable to unlink d/c.txt: Not a directory"

Why it is like that in native git was asked in
http://permalink.gmane.org/gmane.comp.version-control.git/279482. Unless
it is explained why native git why this error is reported JGit should
overwrite the files.

Bug: 474842
Change-Id: I08e23822a577aaf22120c5137eb169b6bd08447b
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java

index 40d8458efdf795023c902fff8b42b7d284d2410d..725ebc0d236726f707fe22c47379d08b532b7f77 100644 (file)
@@ -156,6 +156,34 @@ public class ResetCommandTest extends RepositoryTestCase {
                assertEquals(prevHead, db.readOrigHead());
        }
 
+       @Test
+       public void testHardResetWithConflicts_DoOverWriteUntrackedFile()
+                       throws JGitInternalException,
+                       AmbiguousObjectException, IOException, GitAPIException {
+               setupRepository();
+               git.rm().setCached(true).addFilepattern("a.txt").call();
+               assertTrue(new File(db.getWorkTree(), "a.txt").exists());
+               git.reset().setMode(ResetType.HARD).setRef(Constants.HEAD)
+                               .call();
+               assertTrue(new File(db.getWorkTree(), "a.txt").exists());
+               assertEquals("content", read(new File(db.getWorkTree(), "a.txt")));
+       }
+
+       @Test
+       public void testHardResetWithConflicts_DoDeleteFileFolderConflicts()
+                       throws JGitInternalException,
+                       AmbiguousObjectException, IOException, GitAPIException {
+               setupRepository();
+               writeTrashFile("d/c.txt", "x");
+               git.add().addFilepattern("d/c.txt").call();
+               FileUtils.delete(new File(db.getWorkTree(), "d"), FileUtils.RECURSIVE);
+               writeTrashFile("d", "y");
+
+               git.reset().setMode(ResetType.HARD).setRef(Constants.HEAD)
+                               .call();
+               assertFalse(new File(db.getWorkTree(), "d").exists());
+       }
+
        @Test
        public void testResetToNonexistingHEAD() throws JGitInternalException,
                        AmbiguousObjectException, IOException, GitAPIException {
index fc4cc90937727597bd3cefada37d071fad151508..12ceb74abb12c210a4a3d401912891c19c9dde49 100644 (file)
@@ -354,8 +354,16 @@ public class DirCacheCheckout {
                                // The index entry is missing
                                if (f != null && !FileMode.TREE.equals(f.getEntryFileMode())
                                                && !f.isEntryIgnored()) {
-                                       // don't overwrite an untracked and not ignored file
-                                       conflicts.add(walk.getPathString());
+                                       if (failOnConflict) {
+                                               // don't overwrite an untracked and not ignored file
+                                               conflicts.add(walk.getPathString());
+                                       } else {
+                                               // failOnConflict is false. Putting something to conflicts
+                                               // would mean we delete it. Instead we want the mergeCommit
+                                               // content to be checked out.
+                                               update(m.getEntryPathString(), m.getEntryObjectId(),
+                                                               m.getEntryFileMode());
+                                       }
                                } else
                                        update(m.getEntryPathString(), m.getEntryObjectId(),
                                                m.getEntryFileMode());
@@ -390,6 +398,9 @@ public class DirCacheCheckout {
                        if (f != null) {
                                // There is a file/folder for that path in the working tree
                                if (walk.isDirectoryFileConflict()) {
+                                       // We put it in conflicts. Even if failOnConflict is false
+                                       // this would cause the path to be deleted. Thats exactly what
+                                       // we want in this situation
                                        conflicts.add(walk.getPathString());
                                } else {
                                        // No file/folder conflict exists. All entries are files or