Có lệnh Git nhanh để xem phiên bản cũ của tệp không?


1510

Có một lệnh trong Git để xem (được đổ vào thiết bị xuất chuẩn hoặc trong $PAGERhoặc $EDITOR) một phiên bản cụ thể của một tệp cụ thể không?



Nếu bạn đến câu hỏi này vì bạn muốn kiểm tra phiên bản cũ hơn của tệp nhị phân (ví dụ: hình ảnh), thì tốt hơn là thực hiện kiểm tra cam kết cũ, xem những gì bạn cần xem, sau đó quay lại TRƯỚC. Vì thế, hãy làm git checkout <sha1-of-the-commit-you-need>, sau đó,git checkout HEAD
Homero Esmeraldo

Câu trả lời:


1731

Bạn có thể sử dụng git showvới một đường dẫn từ thư mục gốc của kho lưu trữ ( ./hoặc ../cho đường dẫn tương đối):

$ git show REVISION:path/to/file

Thay thế REVISIONbằng sửa đổi thực tế của bạn (có thể là Git commit SHA, tên thẻ, tên chi nhánh, tên cam kết tương đối hoặc bất kỳ cách nào khác để xác định một cam kết trong Git)

Ví dụ: để xem phiên bản của tệp <repository-root>/src/main.ctừ 4 lần xác nhận trước, hãy sử dụng:

$ git show HEAD~4:src/main.c

Git cho Windows yêu cầu gạch chéo về phía trước ngay cả trong các đường dẫn liên quan đến thư mục hiện tại. Để biết thêm thông tin, hãy kiểm tra trang người đàn ông cho git-show.


5
Điều đó dường như không thực sự hiệu quả - bạn đã thử chưa? Đối với "git show HEAD: path / to / file.c", tôi gặp lỗi "đối số mơ hồ".
mike

2
Phải là con đường hoàn chỉnh, từ đầu git repo
richq

20
Nếu bạn đang ở trên cửa sổ, nó có thể là một thứ phân cách đường dẫn; nếu tôi thực hiện git show HEAD: dir \ subir \ file, tôi nhận được đối số không rõ ràng. Nếu tôi thực hiện git show HEAD: dir / subir / file, nó hoạt động như mong đợi.
Matt McMinn

12
Đường dẫn bạn phải cung cấp sau: là từ thư mục gốc của kho git. (điều này đã được đưa ra dưới đây như một câu trả lời nhưng tôi nghĩ nó được dự định như là một nhận xét về câu trả lời này)
MatrixFrog

9
Nếu bạn muốn xem nó trong phần tách Vim để chúng cuộn lại với nhau, tôi đã viết một bài đăng blog ngắn cho biết cách thực hiện điều đó.
Flaviu

257

Làm điều này theo ngày trông như thế này:

git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt

Lưu ý rằng điều đó HEAD@{2013-02-25}có nghĩa là "nơi ĐẦU TIÊN vào 2013 / 02-25" trong kho lưu trữ này (sử dụng reflog ), chứ không phải "cam kết cuối cùng trước 2013 / 02-25 trong chi nhánh này trong lịch sử".


5
Tuyệt vời. Tiết kiệm rất nhiều thời gian của tôi thay vì đi đến github và nhìn vào cam kết.
Fizer Khan

"Dấu chấm" trên đường dẫn tệp là vấn đề của tôi. Cảm ơn!
tomasarad

5
Lệnh này hữu ích với masterthay vì HEAD@{2013-02-25}, nếu bạn ở trong một chi nhánh
funroll

1
Bạn có thể bao gồm thời gian, à la git log --since='2016-04-28 23:59:59 +0100'?
dumbledad

7
Thực tế cú pháp này sử dụng reflog rất quan trọng và cần được làm nổi bật mạnh mẽ, bởi vì reflog không chứa tất cả các xác nhận . Xem blog.endpoint.com/2014/05/git-checkout-at-specific-date.html
Alice Heaton

113

Nếu bạn thích GUI, bạn có thể sử dụng gitk:

  1. bắt đầu gitk với:

    gitk /path/to/file
    
  2. Chọn sửa đổi ở phần trên cùng của màn hình, ví dụ như theo mô tả hoặc ngày. Theo mặc định, phần dưới của màn hình hiển thị độ lệch cho phiên bản đó, (tương ứng với nút radio "vá").

  3. Để xem tập tin cho phiên bản đã chọn:

    • Nhấp vào nút radio "cây". Điều này sẽ hiển thị gốc của cây tập tin tại phiên bản đó.
    • Đi sâu vào tập tin của bạn.

7
Điều này cũng hoạt động với tig , đó là một người xem repit git repo.
Matthew G

1
@Paul Slocum: Có thể vì lệnh này không phải là lệnh thông thường, không phải là tích hợp của git. Tôi nghĩ lệnh này chỉ hoạt động cho Windows.
Envil

Lưu ý rằng điều này dường như chỉ hoạt động nếu bạn bắt đầu từ thư mục gốc của kho git của bạn.
Marc

Nếu bạn muốn kiểm tra một bản sửa đổi nhất định với gitk, bạn cũng có thể sử dụng phím tắt này : gitk REVISION /path/to/file. Điều này có thể có ích khi bạn muốn kiểm tra một phiên bản nhất định chẳng hạn.
Christian.D

89

Bạn cũng có thể chỉ định một commit hash(thường được gọi là commit ID) với git showlệnh .


Tóm lại

git show <commitHash>:/path/to/file


Từng bước một

  1. Hiển thị nhật ký của tất cả các thay đổi cho một tệp nhất định với git log /path/to/file
  2. Trong danh sách các thay đổi được hiển thị, nó hiển thị commit hashnhư commit 06c98...(06c98 ... là hàm băm cam kết)
  3. Sao chép commit hash
  4. Chạy lệnh git show <commitHash>:/path/to/filebằng cách sử dụng commit hashbước 3 và path/to/filebước 1.

Lưu ý: việc thêm ./khi chỉ định đường dẫn tương đối có vẻ quan trọng, nghĩa làgit show b2f8be577166577c59b55e11cfff1404baf63a84:./flight-simulation/src/main/components/nav-horiz.html .


1
trong trường hợp bạn không biết đường dẫn đến tập tin, hãy sử dụng git show <SHA1> --name-onlyđể có được nó.
Tiina

lệnh này op - thậm chí tự động hoàn thành từ bộ nhớ - đã được thử nghiệm trên một thư mục đã xóa ... không thể nhận được nhiều op hơn gg
treyBake

43

Ngoài câu trả lời của Jim Hunziker ,

bạn có thể xuất tệp từ bản sửa đổi thành,

git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt > old_fileInCurrentDirectory.txt

Hi vọng điêu nay co ich :)


23

Để nhanh chóng thấy sự khác biệt với các phiên bản cũ hơn của tệp:

git show -1 filename.txt > để so sánh với lần sửa đổi cuối cùng của tập tin

git show -2 filename.txt > để so sánh với lần sửa đổi thứ 2

git show -3 fielname.txt > để so sánh với lần sửa đổi thứ 3 cuối cùng


18
Các lệnh đó cho thấy sự khác biệt với phiên bản hiện tại đối với tôi nhưng không hiển thị toàn bộ tệp.
Jean Paul

18

git log -psẽ hiển thị cho bạn không chỉ các bản ghi cam kết mà còn cả độ lệch của từng cam kết (ngoại trừ các cam kết hợp nhất). Sau đó, bạn có thể nhấn /, nhập tên tệp và nhấn enter. Nhấn nhoặc pđể đi đến lần xuất hiện tiếp theo / trước đó. Bằng cách này, bạn sẽ không chỉ nhìn thấy những thay đổi trong tệp mà còn cả thông tin cam kết.


3
Có vẻ như git log -pmcũng sẽ hiển thị các cam kết hợp nhất.
sanbor

2
Bạn cũng có thể chạy git log -p -- filename.txtđể hạn chế lịch sử chỉ với tệp mong muốn.
Jean Paul

3

Bạn có thể sử dụng tập lệnh như thế này để kết xuất tất cả các phiên bản của tệp thành các tệp riêng biệt:

ví dụ

git_dump_all_versions_of_a_file.sh path/to/somefile.txt

Lấy kịch bản ở đây làm câu trả lời cho một câu hỏi tương tự khác


1
git_root, git_log_shortgit_log_message_for_commitđang mất tích.
mogsie

Nắm bắt tốt! Tôi đã đăng gấp đôi câu trả lời này lên 2 điểm khác nhau, và chỉ xóa cái này và liên kết với cái kia, nơi mọi người nói với tôi về điều này trước khi ... cảm ơn @mogsie!
Brad

Kịch bản này rất hữu ích!
Xman

3

CÁCH 1: (Tôi thích cách này)

  1. Tìm id xác nhận với:git reflog
  2. Liệt kê các tập tin từ cam kết git diff-tree --no-commit-id --name-only -r <commitHash>

ví dụ: git diff-tree --no-commit-id --name-only -r d2f9ba4// "d2f9ba4" là id xác nhận từ "1."

  1. Mở tệp cần thiết bằng lệnh:

git show <commitHash>:/path/to/file

ví dụ: git show d2f9ba4:Src/Ext/MoreSwiftUI/ListCustom.swift// "Src / ..." là đường dẫn tệp từ "2."

CÁCH 2:

  1. Tìm id xác nhận với:git reflog
  2. thực hiện thiết lập lại cứng cho cam kết này: git reset --hard %commit ID%

thiết lập lại git - cho c14809fa

  1. thực hiện bất kỳ thay đổi không cần thiết và thực hiện cam kết mới vào chi nhánh cần thiết :)

0

Giúp tìm nạp nhiều tệp từ một phiên bản nhất định

Khi cố gắng giải quyết xung đột hợp nhất, người trợ giúp này rất hữu ích:

#!/usr/bin/env python3

import argparse
import os
import subprocess

parser = argparse.ArgumentParser()
parser.add_argument('revision')
parser.add_argument('files', nargs='+')
args = parser.parse_args()
toplevel = subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).rstrip().decode()
for path in args.files:
    file_relative = os.path.relpath(os.path.abspath(path), toplevel)
    base, ext = os.path.splitext(path)
    new_path = base + '.old' + ext
    with open(new_path, 'w') as f:
        subprocess.call(['git', 'show', '{}:./{}'.format(args.revision, path)], stdout=f)

GitHub ngược dòng .

Sử dụng:

git-show-save other-branch file1.c path/to/file2.cpp

Kết quả: phần sau chứa các phiên bản thay thế của tệp:

file1.old.c
path/to/file2.old.cpp

Bằng cách này, bạn giữ phần mở rộng tệp để trình soạn thảo của bạn không phàn nàn và có thể dễ dàng tìm thấy tệp cũ ngay bên cạnh tệp mới hơn.


@MickeyPerlstein nếu bạn có thể đạt được giao diện tương tự với việc triển khai tốt hơn, tôi sẽ nghe thấy.
Ciro Santilli 冠状 病毒 审查 事件 法轮功

có thể tôi không hiểu (và nếu vậy, lời xin lỗi của tôi) nhưng không phải chỉ là: "phiên bản git show: ./ path> new_path"?
Mickey Perlstein

@MickeyPerlstein hi, vâng, lệnh của tôi tạo CLI đó, nhưng nó lặp lại trên nhiều tệp và tạo tên đầu ra từ đầu vào, vì vậy bạn không phải nhập quá nhiều. Tất nhiên không có gì mang tính cách mạng, nhưng thuận tiện.
Ciro Santilli 冠状 病毒 审查 事件 法轮功
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.