Git 分支 A 和 B 之间的差异,select 一组文件模式更改,将这些更改重置为分支 A
Git diff between branch A & B, select a set of file mode changes, reset those changes to branch A
我愿意
第 1 步)使分支 A 和 B 之间存在 Git 差异,
第 2 步)select 一组更改(select 那些更改,其中文件权限从模式 100755 更改为模式 100644),
步骤 3) 将那些 selected 更改重置为分支 A(或从分支 B 中挑选更改)。
如何使用 git?
部分解:
第 1 步和第 2 步)我能够列出那些具有
的文件
git diff --name-only "A" "B" | grep 'mode change 100755 => 100644'
步骤 3) 如何将那些 selected 文件模式更改重置为分支 A(或从分支 B 中挑选更改)?
我只想将步骤 1 中 selected 文件的文件状态恢复到它们在分支 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 的回答:
使用
在 git 内部更改 permission/mode
git update-index --chmod=+x file.php
解决方案
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"
```
不清楚 "reset" 是什么意思。差异与构成差异的提交本身不同。您想要构成这些更改的所有提交(带有消息和作者身份)还是只想要最终结果?听起来您是在谈论基于 B 中的更改子集在 A 上创建一组 new 更改。
要 cherry-pick 提交,查看 git log B
以识别它们,然后在 A:
git cherry-pick [COMMIT_HASH]
要合并 或分解 cherry-picks 到单个提交中,请执行:
git cherry-pick --no-commit [COMMIT_HASH1]
git cherry-pick --no-commit [COMMIT_HASH2]
...
git commit -a
要分解 cherry-pick,即cherry-pick 更改在 提交中:
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 file is the right one")并且您不关心它是如何到达那里的(提交元数据),那么只需从该分支检出文件内容并提交它们:
git checkout origin/B -- path/to/file
...
git commit -a
git diff --raw A B | sed -n '/^:100755 100644/ s/[^\t]*.//p'
将列出您要从中选择的路径,对其进行编辑并通过 a-x 或 a+x 将其通过管道传输到 xargs -d\n chmod
,具体取决于您是在 A 上并希望丢失 x 位还是在 B 上并想恢复它。
在 Windows 上,可执行位是无意义的,您可以直接更新索引条目,而不是 chmod a+x
ing 文件然后让 git 添加更新索引,git update-index --chmod=+x
设置索引位的文件,-x
清除它。
最初的问题是 Windows,但我在 Mac 上遇到了同样的问题。 @jthill 的建议很有帮助,但 sed 命令对我来说太贪心了——它会消化第一列和一半的文件路径,只留下每个文件名的最后一位。
Mac 上的 sed 似乎不能很好地解析 \t
(一般来说,它似乎也不会 \s
用于白色 space) .我最终使用了一致的列宽并删除了一定数量的字符:
# 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
我愿意
第 1 步)使分支 A 和 B 之间存在 Git 差异,
第 2 步)select 一组更改(select 那些更改,其中文件权限从模式 100755 更改为模式 100644),
步骤 3) 将那些 selected 更改重置为分支 A(或从分支 B 中挑选更改)。
如何使用 git?
部分解:
第 1 步和第 2 步)我能够列出那些具有
的文件git diff --name-only "A" "B" | grep 'mode change 100755 => 100644'
步骤 3) 如何将那些 selected 文件模式更改重置为分支 A(或从分支 B 中挑选更改)? 我只想将步骤 1 中 selected 文件的文件状态恢复到它们在分支 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 的回答:
使用
在 git 内部更改 permission/modegit update-index --chmod=+x file.php
解决方案
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"
```
不清楚 "reset" 是什么意思。差异与构成差异的提交本身不同。您想要构成这些更改的所有提交(带有消息和作者身份)还是只想要最终结果?听起来您是在谈论基于 B 中的更改子集在 A 上创建一组 new 更改。
要 cherry-pick 提交,查看 git log B
以识别它们,然后在 A:
git cherry-pick [COMMIT_HASH]
要合并 或分解 cherry-picks 到单个提交中,请执行:
git cherry-pick --no-commit [COMMIT_HASH1]
git cherry-pick --no-commit [COMMIT_HASH2]
...
git commit -a
要分解 cherry-pick,即cherry-pick 更改在 提交中:
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 file is the right one")并且您不关心它是如何到达那里的(提交元数据),那么只需从该分支检出文件内容并提交它们:
git checkout origin/B -- path/to/file
...
git commit -a
git diff --raw A B | sed -n '/^:100755 100644/ s/[^\t]*.//p'
将列出您要从中选择的路径,对其进行编辑并通过 a-x 或 a+x 将其通过管道传输到 xargs -d\n chmod
,具体取决于您是在 A 上并希望丢失 x 位还是在 B 上并想恢复它。
在 Windows 上,可执行位是无意义的,您可以直接更新索引条目,而不是 chmod a+x
ing 文件然后让 git 添加更新索引,git update-index --chmod=+x
设置索引位的文件,-x
清除它。
最初的问题是 Windows,但我在 Mac 上遇到了同样的问题。 @jthill 的建议很有帮助,但 sed 命令对我来说太贪心了——它会消化第一列和一半的文件路径,只留下每个文件名的最后一位。
Mac 上的 sed 似乎不能很好地解析 \t
(一般来说,它似乎也不会 \s
用于白色 space) .我最终使用了一致的列宽并删除了一定数量的字符:
# 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