変更された場合にgit内のファイルとディレクトリの権限を復元するにはどうすればよいですか?


278

gitチェックアウトがあります。すべてのファイル権限はgitが想定するものとは異なるため、変更されたものとして表示されます。

ファイルのコンテンツに触れずに(アクセス許可を変更したいだけ)すべてのファイルのアクセス許可をgitが想定しているとおりに設定するにはどうすればよいですか?


回答:


572

Gitはfilepermissionを追跡し、を使用してパッチを作成するときにアクセス許可の変更を公開しますgit diff -p。したがって、必要なのは次のとおりです。

  1. リバースパッチを作成する
  2. 権限の変更のみを含める
  3. 作業コピーにパッチを適用します

ワンライナーとして:

git diff -p -R --no-ext-diff --no-color \
    | grep -E "^(diff|(old|new) mode)" --color=never  \
    | git apply

git構成のエイリアスとして追加することもできます...

git config --global --add alias.permission-reset '!git diff -p -R --no-ext-diff --no-color | grep -E "^(diff|(old|new) mode)" --color=never | git apply'

...そして、それを呼び出すことができます:

git permission-reset

シェルがの場合はbash、必ず引用符の'代わりに使用してください。そうしないと、最後に実行したコマンドで置き換えられます。"!gitgit

@MixologicのThxは、単に-Ron を使用するだけgit diffで、面倒なsedコマンドが不要になったことを指摘しています。


3
私はOS Xを使用していますが、これは機能しません。問題はgit applyにあることがわかりました。ファイルのアクセス許可の変更は適用されません。
pepper_chico

15
ああ、うまくいきました。リポジトリのルートとは別のディレクトリから適用しようとしました。git applyはそこでのみ機能します。
pepper_chico

6
sedを逆にする代わりに "git diff -p -R"を実行しない理由はありますか?
Mixologic 2013年

6
@RobQuist muhquのコマンドを使用しても、ローカルの変更が削除されませんでした
ログオン14年

17
取得中fatal: unrecognized input
Tieme

120

試す git config core.fileMode false

git configmanページから:

core.fileMode

falseの場合、インデックスと作業コピーの間の実行可能ビットの違いは無視されます。FATなどの壊れたファイルシステムで役立ちます。git-update-index(1)を参照してください。

デフォルトはtrueですが、リポジトリの作成時にgit-clone(1)またはgit-init(1)が適切にプローブしてcore.fileModeをfalseに設定する場合を除きます。


おかげで、これは私がやったことです。これは機能するため、アクセス許可を追跡しないcvsに非常に使用されます。
デールフォレスター

3
@shovas:これが役に立てて嬉しいです。LinuxとWindowsの間でリポジトリを共有するときに、同様の問題が発生しました。ところで:これがあなたの質問に答えた場合、回答を正しいものとしてマークしてください。
Tim Henigan

git checkout origin/masterサーバーにコミットされたファイル権限をローカルの作業コピーに設定することは可能ですか?なぜなら、ArangoDB用にV8をビルドするたびに、ファイルのアクセス許可が変更されるため、ビルドフォルダー全体へのアクセスが拒否されるからです(昇格された権限でもWindows 7以降)。ビルドプロセスを続行する前に、すべてのローカルファイルの権限を修正する必要があります。core.filemode falseそれも修正できますか?私はgitが私のWindowsマシンにLinuxパーミッションを設定しているのではないかと疑っています。ビルドスクリプトはそれらを保持し、新しく作成されたファイルに同じ権限を適用するだけかもしれません...
CodeManX

に設定filemodeすることにマイナス面があるかどうか疑問に思っていますfalse
ケボロイド

11

Gitは実行可能スクリプト以外のファイル権限を保存しません。git-cache-metaなどを使用して、ファイルの所有権と権限を保存することを検討してください。

Gitは755(実行可能)と644(実行不可)の2種類のモードしか保存できません。ファイルが444の場合、gitには644が格納されます。


14
申し訳ありませんが、これは正しくありません。実際、Gitはアクセス許可を追跡します。
2013

4
おおまかに正確です。git.wiki.kernel.org/index.php/ContentLimitationsを参照してください。設定される正確な権限は、サーバーおよびおそらくクライアントumaskと、構成設定に基づいて表示されます。stackoverflow.com/ a / 12735291/125150を参照してください。
Motti Strom

12
@いいえ、そうではありません。あなたのコメントが非常に多くの賛成を得たとは信じられません。
eisは

@まあ、これはおおよそ正しい。ドキュメント ごと...a mode of 100644, which means it’s a normal file. Other options are 100755, which means it’s an executable file; and 120000, which specifies a symbolic link. The mode is taken from normal UNIX modes but is much less flexible — these three modes are the only ones that are valid for files (blobs) in Git (although other modes are used for directories and submodules).
esmail

9
git diff -p \
| grep -E '^(diff|old mode|new mode)' \
| sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
| git apply

ほとんどの場合に機能しますが、meldなどの外部diffツールがインストールされている場合は、-no-ext-diffを追加する必要があります

git diff --no-ext-diff -p \
    | grep -E '^(diff|old mode|new mode)' \
    | sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
    | git apply

私の状況では必要でした



0

私はWindowsでcygwinのgitを使用していますが、このgit applyソリューションは機能しません。これが私の解決策chmodです。すべてのファイルで実行して、権限をリセットします。

#!/bin/bash
IFS=$'\n'
for c in `git diff -p |sed -n '/diff --git/{N;s/diff --git//g;s/\n/ /g;s# a/.* b/##g;s/old mode //g;s/\(.*\) 100\(.*\)/chmod \2 \1/g;p}'`
do
        eval $c
done
unset IFS


-1

git diff -pmuhquの回答で使用されている場合、すべての不一致が表示されるとは限りません。

  • 私が所有していないファイルについてCygwinでこれを見た
  • 場合モードの変更は完全に無視されcore.filemodeているfalse(MSysGitのデフォルトです)

このコードは、代わりにメタデータを直接読み取ります。

(set -o errexit pipefail nounset;
git ls-tree HEAD -z | while read -r -d $'\0' mask type blob path
do
    if [ "$type" != "blob" ]; then continue; fi;
    case "$mask" in
    #do not touch other bits
    100644) chmod a-x "$path";;
    100755) chmod a+x "$path";;
    *) echo "invalid: $mask $type $blob\t$path" >&2; false;;
    esac
done)

非生産グレードのワンライナー(マスクを完全に置き換えます):

git ls-tree HEAD | perl -ne '/^10(0\d{3}) blob \S+\t(.+)$/ && { system "chmod",$1,$2 || die }'

(「$ '\ 0'」のクレジットはhttp://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.htmlに移動します


-2

最も簡単な方法は、権限を元に戻すことです。@krogerが指摘したように、gitは実行可能なビットのみを追跡します。したがって、おそらくchmod -x filenameそれを修正するために実行する必要があります(または+xそれが必要な場合)。


ここからの例ですgit show:差分--git A / OpenWatch / SRC / ORG /エール/ openwatch / FB / FBUtils.java B / OpenWatch / SRC / ORG /エール/ openwatch / FB / FBUtils.javaインデックスcd6fa6a..e5b0935 100644 それ太字のビットはファイルのアクセス許可です。
Conrado 2013

これも私にとって最も簡単に思えました。残念ながら、Conradoと同じ問題が発生し100644ました100755。許可をからに変更できませんでした。私はあなたが反対票を投じる価値があるとは思いません。Gitは反対票です。それは非常に多くの異なるレベルで非常に多くの方法で壊れています...
jww

-2

このetckeeperツールは、アクセス許可を次のように処理できます。

etckeeper init -d /mydir

以外のディレクトリにも使用できます/etc

パッケージマネージャーを使用してインストールするか、上記のリンクからソースを取得します。


4
それは何に権限を設定しますか?Gitメタデータを読み取ったり、Gitを呼び出したりしない場合、OPが要求したことは実行されません。
ivan_pozdeev 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.