分支A和A之间的Git差异。 B,选择一组文件模式更改,将这些更改重置为分支A.

时间:2017-04-25 16:09:49

标签: git file-permissions git-diff git-reset

我想

步骤1)在分支A和A之间制作Git diff。 B,

步骤2)选择一组更改(选择那些更改,其中文件权限从模式100755更改为模式100644),

步骤3)将选定的更改重置为分支A(或分支B中的樱桃选择更改)。

我如何使用git?

部分解决方案:

第1步& 2)我能够列出那些有

的文件

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

步骤3)如何将选定的文件模式更改重置为分支A(或从分支B更改樱桃选择)? 我只想将步骤1中选择的文件的文件状态恢复到它们在分支A中的状态。

注意:我有几千个文件,所以逐个挑选樱桃不是解决方案。

@jthill:不幸的是,在MINGW64(Windows)上执行chmod时,它可能没有任何效果,可能是因为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

因为我在Windows中开发,并且repos存储在Linux中,基于chmod的权限更改不是我的方式,因为Windows不支持类似Linux的755或644权限。

@jthill然而给了我一个良好的开端,有一个有效的解决方案。谢谢!

我发现了一种改进的方法,适用于Windows& Linux也是基于@jthill的回答:

  1. 使用

    在git内部更改权限/模式更改
    git update-index --chmod=+x file.php
    
  2. 解决方案

    1。文件模式更改:模式更改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。文件模式更改:模式更改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"
    

    ```

3 个答案:

答案 0 :(得分:1)

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

将列出您要选择的路径,对其进行编辑并使用ax或+ x将其传输到xargs -d\\n chmod,具体取决于您是否在A上并且想要丢失x位或在B上并希望恢复它。

在Windows上,可执行位无意义,您可以直接更新索引条目,而不是chmod a+x文件然后让git add更新索引,git update-index --chmod=+x文件来设置位在索引-x中清除它。

答案 1 :(得分:0)

不清楚你的意思"重置"。 Diff与构成分歧的提交本身不同。您是否想要构成这些更改的所有提交(带有消息和作者)或者您是否只想获得最终结果?听起来你正在谈论根据B中的一部分变化在A上创建一个新的变更集。

cherry-pick 提交,请查看git log B以识别它们,然后在A:

git cherry-pick [COMMIT_HASH]

合并分解樱桃选择,请执行以下操作:

git cherry-pick --no-commit [COMMIT_HASH1]
git cherry-pick --no-commit [COMMIT_HASH2]
...
git commit -a

分解 cherry-pick(s),即在提交中挑选

git cherry-pick --no-commit [COMMIT_HASH]
...
git checkout some_file/we/dont/care/about
git checkout another/file/we/dont/care/about
...
git reset -p file/we/want/some/changes/from
git commit -a

checkout放弃给定文件的更改。 reset -p是互动的,反之如git add -p。您已经对文件进行了一些更改,并选择了重置更改。你留下的任何东西都是你将要做的瘦身樱桃挑选的一部分。

最后,如果您只想整个文件更改(即" B' s文件是正确的#34;)并且您不关心它是如何做到的到达那里(提交元数据),然后只检查该分支中的文件内容并提交它们:

git checkout origin/B -- path/to/file
...
git commit -a

答案 2 :(得分:0)

最初的问题是针对 Windows 的,但我在 Mac 上遇到了同样的问题。 @jthill 的建议非常有帮助,但在我的情况下 sed 命令过于贪婪——它会消化第一列以及文件路径的一半,只留下每个文件名的最后一位。

Mac 上的 sed 似乎不能很好地解析 \t(通常,它似乎也没有将 \s 用于空格)。我最终使用了一致的列宽并删除了一定数量的字符:

# Send diff to text file
git diff --raw master update_socio_eco > tmp-diff.txt

# Search for files with mode change from 644 to 755; delete initial 33 characters
# Swap order to 100755 100644 if reverting to 755
sed -nE '/:100644 100755/ s/^:.{32}//p' tmp-diff.txt >tmp-diff2.txt

# Add quotes to capture files with white space
sed -n 's/.*/"&"/p' tmp-diff2.txt >tmp-diff3.txt

# Change file mode (-x to revert to 644, +x to revert to 755)
cat tmp-diff3.txt | xargs chmod -x