tummychow / git-absorb

git commit --fixup, but automatic
https://crates.io/crates/git-absorb
BSD 3-Clause "New" or "Revised" License
3.38k stars 58 forks source link

Getting "old path already occupied" #37

Open jgosmann opened 3 years ago

jgosmann commented 3 years ago

Great tool! Unfortunately, I was trying to absorb some changes today and got this error:

Nov 23 09:17:36.878 CRIT absorb failed, err: old path already occupied

It is not clear to me why am I getting this error, what it means, or how to solve it. :(

tummychow commented 3 years ago

i can't diagnose this issue without more information. that error comes from my patch parsing code, so i need to see the diffs of your git index (git diff --cached) and the commits in your git absorb stack

jgosmann commented 3 years ago

I cannot share the exact diff (it's proprietary source code), but I could locate the issue: I had a symbolic link to a file that I replaced with an actual file. This gives a diff similar to this one:

diff --git a/some-file.ext b/some-file.ext
new file mode 100644
index 0000000000..7cb58a6452
--- /dev/null
+++ b/some-file.ext
@@ -0,0 +1,135 @@
+# File contents following here
tummychow commented 3 years ago

ah... i can see how that would cause this problem

diff --git a/bar b/bar
deleted file mode 120000
index 1910281..0000000
--- a/bar
+++ /dev/null
@@ -1 +0,0 @@
-foo
\ No newline at end of file
diff --git a/bar b/bar
new file mode 100644
index 0000000..e69de29

looks like link and non-link changes get different hunks. that'll require a special case in the parser

jgosmann commented 3 years ago

I've found another case not involving symbolic links where I'm getting this error:

diff --git a/some_path/pvm.spec b/some_path/pvm.spec
index aa58341137..943bacfa2c 100644
--- a/some_path/pvm.spec
+++ b/some_path/pvm.spec
@@ -58,7 +58,7 @@ tar -xzf %{SOURCE0}
 cd pvm3
 tar -xzf %{SOURCE1}
 %patch0 -p0
-#patch1 -p1
+%patch1 -p1
 %patch2 -p1
 %patch3 -p1
 %patch4 -p1
tummychow commented 3 years ago

is that the entire index? this bug requires a diff with two patches that both have the same filename. your example only has one patch in it

jgosmann commented 3 years ago

Yes, that is the entire index.

Maybe the previous commits in the history are the problem? There are still some commits doing things with symlinks.

tummychow commented 3 years ago

Maybe the previous commits in the history are the problem?

yeah that sounds likely, every commit has to get parsed the same way as the index. probably one of them has the same issue where a symlink is being turned into a regular file or vice versa

junkblocker commented 1 year ago

Any plans to fix this? It's a couple of years old now.

Konfekt commented 6 months ago

Maybe this could be documented more prominently, as symlinking happens quite frequently and thus is a common source of failure

81ninja commented 6 months ago

I've had this problem a few times already, and the solution I found was to find the offending commit by trying

git-absorb -b HEAD~100 --dry-run
git-absorb -b HEAD~50 --dry-run
git-absorb -b HEAD~75 --dry-run
...
git-absorb -b HEAD~nn --dry-run

etc until I nailed down the offending commit (nn patches ago), then git rebase the repo from since the offending commit with git rebase --onto HEAD~nn HEAD~nn (yes twice the rev number) to change the offending file's mode (previously a symlink, that's be un-linked) by using git ls-files */*/my.file --stage (to show file modes), and finally git update-index --chmod=-x my.file to set permissions to anything other than file mode 12000 (symlink). Then git rebase --continue