2011-10-15 37 views
8

Tôi có a) thư mục hoạt động mà không có thư mục .gitb) một kho lưu trữ. a là một số sửa đổi ở giữa lịch sử của b.Tìm Bản sửa đổi Git của Thư mục Làm việc Thiếu Thư mục .git

Tôi làm cách nào để biết được bản sửa đổi nào a kết quả phù hợp trong b?

Tôi nghĩ về một shellscript làm một diff từ thư mục làm việc cho tất cả các bản sửa đổi và chọn một trong đó có ít nhất (hy vọng 0) sự khác biệt.

Điều đó sẽ hơi thô (và tôi không chắc chắn cách thực hiện), có cách nào dễ dàng hơn không?

Trả lời

4

Bạn có thể viết tập lệnh để chạy diff gitdir workdir | wc -c cho từng cam kết. Sau đó, bạn có thể đối chiếu kết quả và nói rằng cam kết có chênh lệch nhỏ nhất (được đo bằng wc -c) là cam kết gần nhất với thư mục làm việc trần.

Đây là những gì nó có thể trông giống như bằng Python:

find_closest_sha1.py:

#!/usr/bin/env python 
import subprocess 
import shlex 
import sys 
import os 
import operator 

gitdir,workdir=map(os.path.realpath,sys.argv[1:3]) 
os.chdir(gitdir) 
proc=subprocess.Popen(shlex.split('git rev-list --all'),stdout=subprocess.PIPE) 
shas,err=proc.communicate() 
shas=shas.split() 
head=shas[0] 
data={} 
for sha1 in shas: 
    subprocess.Popen(shlex.split('git checkout {s}'.format(s=sha1)), 
          stderr=open('/dev/null')).wait() 
    proc=subprocess.Popen(shlex.split('diff {g} {w}'.format(g=gitdir,w=workdir)), 
          stdout=subprocess.PIPE) 
    out,err=proc.communicate() 
    distance=len(out) 
    data[sha1]=distance 
answer=min(data.items(),key=operator.itemgetter(1))[0] 
print('closest match: {s}'.format(s=answer)) 
subprocess.Popen(shlex.split('git checkout {h}'.format(h=head)), 
       stderr=open('/dev/null')).wait() 

Ví dụ:

% rsync -a gitdir/ workdir/ 
% cd workdir 
% git checkout HEAD~10 
HEAD is now at b9fcebf... fix foo 

% cd .. 
% /bin/rm -rf workdir/.git 
% find_closest_sha1.py gitdir workdir 
closest match: b9fcebfb170785c19390ebb4a9076d11350ade79 
+0

Tập lệnh python hoàn toàn thất bại khi tôi kiểm tra. Nó đưa ra một cam kết hoàn toàn sai. –

1

Bạn có thể giảm số lần sửa đổi bạn phải kiểm tra với pickaxe. Khác biệt thư mục làm việc của bạn với bản sửa đổi mới nhất và chọn một số dòng khác nhau trông hiếm nhất có thể. Nói bản sửa đổi mới nhất của bạn có một dòng có chứa foobar nhưng thư mục công việc của bạn không; chạy git log -Sfoobar kết quả đầu ra tất cả các cam kết thêm hoặc xóa foobar. Bây giờ bạn có thể di chuyển kho lưu trữ của bạn trở lại bản sửa đổi đầu tiên (mới nhất) trên danh sách đó, vì tất cả các bản sửa đổi sau đó sẽ khác với thư mục công việc của bạn. Lặp lại với một sự khác biệt cho đến khi bạn tìm thấy bản sửa đổi chính xác.

1

Vì git sử dụng kho lưu trữ tệp nội dung, nên có thể tìm thấy một cây tùy ý trong đó ở đâu đó, nhưng tôi không biết chi tiết. Tôi đoán bạn có thể sao chép các tệp từ thư mục công việc tách ra vào thư mục làm việc của kho, sau đó cam kết mọi thứ, bằng cách nào đó tìm ra giá trị băm của đối tượng cây được tạo bởi cam kết và tìm kiếm các cam kết hiện có cho một tham chiếu cùng một cây .

Để làm việc này, cây rõ ràng sẽ cần phải khớp hoàn hảo, vì vậy bạn không được nhận bất kỳ tệp nào không được theo dõi vào cam kết (chẳng hạn như tệp đối tượng, sao lưu trình chỉnh sửa, v.v.).

Chỉnh sửa: Tôi vừa thử trên một kho (với git cat-file commit HEAD để hiển thị đối tượng cây ở HEAD và tìm kiếm kết quả là git log --pretty=raw cho băm cây đó) và nó không hoạt động (tôi không tìm thấy băm trong lịch sử). Tôi đã nhận được một loạt cảnh báo về chuyển đổi CRLF khi tôi thực hiện cam kết, do đó có thể đã xảy ra sự cố, tức là bạn có thể nhận được các băm khác nhau cho cùng một cây tùy thuộc vào cách git của bạn được định cấu hình để mangle tệp văn bản. Tôi đang đánh dấu câu trả lời cho cộng đồng wiki này trong trường hợp ai đó biết cách thực hiện điều này một cách đáng tin cậy.

0

Giả sử rằng trong cây và b/.git bỏ qua các cài đặt như khi chúng được tạo và rằng không có bất kỳ tập tin không bị bỏ qua không được bỏ qua trong cây làm việc, bạn sẽ có thể chạy một cái gì đó như thế này.

Chiến lược là tạo lại id git của cây đang hoạt động và sau đó tìm kiếm bất kỳ cam kết nào chứa cây này.

# work from detached working tree 
cd a 

# Use existing repository and a temporary index file 
GIT_DIR=b/.git 
GIT_INDEX_FILE=/tmp/tmp-index 
export GIT_DIR GIT_INDEX_FILE 

# find out the id of the current working tree 
git add . && 
tree_id=$(git write-tree) && 
rm /tmp/tmp-index 

# find a commit that matches the tree 
for commit in $(git rev-list --all) 
do 
    if test "$tree_id" = "$(git rev-parse ${commit}^{tree})"; then 
     git show "$commit" 
     break 
    fi 
done 

unset GIT_DIR 
unset GIT_INDEX_FILE 
Các vấn đề liên quan