Search code examples
gitfile-permissionsgit-diffgit-reset

Git diff between branch A & B, select a set of file mode changes, reset those changes to branch A


I would like to

Step 1) make Git diff between branch A & B,

Step 2) select a set of changes (select those changes, where file permission is changed from mode 100755 to mode 100644),

Step 3) reset those selected changes to branch A (or cherry pick changes from branch B).

How can I do with git?

Partial solution:

Step 1 & 2) I was able to list those files, which have

git diff --name-only "A" "B" | grep 'mode change 100755 => 100644'

Step 3) How can I reset those selected file mode changes to branch A (or cherry pick changes from branch B)? I just want to restore the file states of files selected in step 1 to their state they had in branch A.

Note: I have several thousand files, so cherry picking one by one is not a solution.

@jthill: Unfortunately, when doing chmod on MINGW64 (Windows) it has no effect, likely because of Windows.

$ ls -la admin/langdoc.php
-rw-r--r-- 1 klor 197121 9844 Apr 25 23:04 admin/langdoc.php
$ chmod 755 admin/langdoc.php
$ ls -la admin/langdoc.php
-rw-r--r-- 1 klor 197121 9844 Apr 25 23:04 admin/langdoc.php

Because I'm developing in Windows, and repos are stored in Linux, the chmod based permission changes are not my way, because Windows doesn't support Linux-like 755 or 644 permissions.

@jthill however gave me a good start to have a working solution. Thanks!

I found an improved way, which works on Windows & Linux, too, based on answer of @jthill:

  1. changing the permission/mode change internally within git, using

    git update-index --chmod=+x file.php
    

Solution for

1. file mode changes: mode change 100755 => 100644

```

# 1st line just creates a file to be able to check if mode of same files are changing
git diff --raw "A" "B" | sed -n '/^:100755 100644/ s/[^\t]*.//p' > diff_mode_100755.txt
# 2nd is doing the mode change from 100755 to 100644
git diff --raw "A" "B" | sed -n '/^:100755 100644/ s/[^\t]*.//p' | xargs -d\\n git update-index --chmod=+x
git commit -m "Restore original 755 file mode"

```

2. file mode changes: mode change 100644 => 100755

```

# 1st line just creates a file to be able to check if mode of same files are changing
git diff --raw "A" "B" | sed -n '/^:100644 100755/ s/[^\t]*.//p' > diff_mode_100644.txt
# 2nd is doing the mode change from 100644 to 100755
git diff --raw "A" "B" | sed -n '/^:100644 100755/ s/[^\t]*.//p' | xargs -d\\n git update-index --chmod=-x
git commit -m "Restore original 644 file mode"

```


Solution

  • git diff --raw A B | sed -n '/^:100755 100644/ s/[^\t]*.//p'
    

    will list the paths you want to choose from, edit that and pipe it to xargs -d\\n chmod with a-x or a+x depending on whether you're on A and want to lose the x bit or on B and want to restore it.

    On Windows, where the executable bit is meaningless you can just update the index entries directly, instead of chmod a+xing the files then letting git add update the index, git update-index --chmod=+x the files to set the bit in the index, -x to clear it.