Làm cách nào để khôi phục quyền của các tệp và thư mục trong git nếu chúng đã được sửa đổi?


278

Tôi có một kiểm tra git. Tất cả các quyền của tệp khác với những gì git nghĩ rằng chúng nên được hiển thị dưới dạng sửa đổi.

Không chạm vào nội dung của các tệp (chỉ muốn sửa đổi các quyền), làm cách nào để đặt tất cả các quyền của tệp thành git nghĩ chúng nên như thế nào?


Câu trả lời:


572

Git theo dõi quá trình lưu trữ và hiển thị các thay đổi quyền khi tạo các bản vá bằng cách sử dụng git diff -p. Vì vậy, tất cả những gì chúng ta cần là:

  1. tạo một bản vá ngược
  2. chỉ bao gồm các thay đổi quyền
  3. áp dụng các bản vá cho bản sao làm việc của chúng tôi

Như một lớp lót:

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

bạn cũng có thể thêm nó dưới dạng bí danh vào cấu hình git của mình ...

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'

... và bạn có thể gọi nó thông qua:

git permission-reset

Lưu ý, nếu bạn shell là bash, hãy đảm bảo sử dụng 'thay vì "dấu ngoặc kép xung quanh !git, nếu không nó sẽ được thay thế bằng gitlệnh cuối cùng bạn đã chạy.

Thx để @Mixologic đã chỉ ra rằng bằng cách đơn giản sử dụng -Rtrên git diff, những rườm rà sedlệnh không còn cần thiết.


3
Tôi đang ở OS X, cái này không hoạt động. Tôi đã xác định vấn đề là trong git áp dụng. Nó không áp dụng các thay đổi quyền tập tin.
pepper_chico

15
Ồ, nó đã hoạt động, tôi đã cố gắng áp dụng từ một thư mục khác với thư mục gốc. git chỉ áp dụng ở đó.
pepper_chico

6
Có một số lý do bạn sẽ không chỉ làm "git diff -p -R" thay vì làm sed để làm cho nó đảo ngược?
Mixologic

6
@RobQuist các thay đổi cục bộ của tôi không bị xóa khi sử dụng lệnh của muhqu
logion

17
Tôi đang nhận đượcfatal: unrecognized input
Tieme

120

Thử git config core.fileMode false

Từ git configtrang người đàn ông:

core.fileMode

Nếu sai, sự khác biệt bit thực thi giữa chỉ mục và bản sao làm việc bị bỏ qua; hữu ích trên các hệ thống tập tin bị hỏng như FAT. Xem git-update-index (1) .

Mặc định là đúng, ngoại trừ git-clone (1) hoặc git-init (1) sẽ thăm dò và đặt core.fileMode sai nếu thích hợp khi kho được tạo.


Cảm ơn, đây là những gì tôi đã làm. Rất được sử dụng để cvs không theo dõi quyền để điều này hoạt động.
Dale Forester

3
@shovas: Tôi rất vui vì điều này đã giúp. Tôi gặp một vấn đề tương tự khi chia sẻ repos giữa Linux và Windows. BTW: nếu điều này trả lời câu hỏi của bạn, vui lòng đánh dấu câu trả lời là chính xác.
Tim Henigan

Có thể git checkout origin/masterđặt quyền truy cập tệp được cam kết với máy chủ vào bản sao làm việc cục bộ của tôi không? Bởi vì bất cứ khi nào tôi xây dựng V8 cho ArangoDB, các quyền của tệp sẽ bị thay đổi để quyền truy cập bị từ chối đối với toàn bộ thư mục bản dựng (ngay cả với quyền nâng cao; đó là Windows 7+). Tôi cần sửa tất cả các quyền của tệp cục bộ trước khi có thể tiếp tục quá trình xây dựng. Có thể core.filemode falsesửa nó quá không? Tôi nghi ngờ git đặt quyền Linux trên máy Windows của tôi. Các tập lệnh xây dựng có thể chỉ bảo tồn chúng và áp dụng các quyền tương tự cho các tệp mới được tạo ...
CodeManX 17/08/2015

Im tự hỏi nếu có bất cứ nhược điểm để thiết lập filemodeđể false!
kevoroid

11

Git không lưu trữ các quyền của tập tin ngoài các tập lệnh thực thi. Cân nhắc sử dụng một cái gì đó như git-cache-meta để lưu quyền sở hữu và quyền của tệp.

Git chỉ có thể lưu trữ hai loại chế độ: 755 (thực thi) và 644 (không thể thực thi). Nếu tập tin của bạn là 444 git sẽ lưu trữ nó có 644.


14
Xin lỗi, nhưng điều này không chính xác. Git, thực sự, theo dõi quyền.
Sẽ

4
Nó gần như chính xác, xem git.wiki.kernel.org/index.php/ContentLimemony . Các quyền chính xác được thiết lập xuất hiện dựa trên máy chủ và có thể là máy khách umaskcũng như cài đặt cấu hình, xem stackoverflow.com/a/12735291/125150 .
Motti Strom

12
@ Sẽ không, nó không. Không thể tin được bình luận của bạn có quá nhiều sự ủng hộ.
eis

@ Sẽ, điều này gần đúng. Theo các tài liệu ...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

sẽ hoạt động trong hầu hết các trường hợp nhưng nếu bạn có các công cụ khác ngoài như cài đặt meld, bạn phải thêm --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

là cần thiết trong tình huống của tôi



0

Tôi sử dụng git từ cygwin trên Windows, git applygiải pháp không hiệu quả với tôi. Đây là giải pháp của tôi, chạy chmodtrên mọi tệp để thiết lập lại quyền của nó.

#!/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 -pđược sử dụng trong câu trả lời của muhqu có thể không hiển thị tất cả các khác biệt.

  • đã thấy điều này trong Cygwin cho các tập tin tôi không sở hữu
  • thay đổi chế độ được bỏ qua hoàn toàn nếu core.filemodefalse(đó là mặc định cho MSysGit)

Mã này đọc siêu dữ liệu trực tiếp thay thế:

(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)

Một lớp lót không sản xuất (thay thế hoàn toàn mặt nạ):

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

(Tín dụng cho "$ '\ 0'" đi tới http://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.html )


-2

Cách dễ nhất để làm là chỉ cần thay đổi các quyền trở lại. Như @kroger lưu ý git chỉ theo dõi các bit thực thi. Vì vậy, có lẽ bạn chỉ cần chạy chmod -x filenameđể sửa nó (hoặc +xnếu đó là những gì cần thiết.


Dưới đây là một ví dụ từ git show: diff --git a / OpenWatch / src / org / bia / openwatch / fb / FBUtils.java b / OpenWatch / src / org / bia / openwatch / fb / index FBUtils.java cd6fa6a..e5b0935 100.644 Đó bit in đậm có quyền truy cập tập tin.
Conrado

Điều này dường như dễ dàng nhất đối với tôi, quá. Thật không may, tôi gặp phải vấn đề tương tự như Conrado - Tôi không thể thay đổi sự cho phép của 100644để 100755. Tôi không nghĩ rằng bạn xứng đáng với một downvote; Git nên được bỏ phiếu. Nó bị phá vỡ theo nhiều cách ở nhiều cấp độ khác nhau ...
jww

-2

Công etckeepercụ này có thể xử lý các quyền và với:

etckeeper init -d /mydir

Bạn có thể sử dụng nó cho các dir khác hơn /etc.

Cài đặt bằng cách sử dụng trình quản lý gói của bạn hoặc lấy nguồn từ liên kết trên.


4
Nó đặt quyền gì? Nếu nó không đọc siêu dữ liệu Git hoặc gọi Git, thì nó không làm những gì OP yêu cầu.
ivan_pozdeev
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.