Những lời khuyên bạn đã đưa ra là thiếu sót. Đặt vô điều kiện GIT_AUTHOR_DATE trong một --env-filter
sẽ viết lại ngày của mỗi cam kết. Ngoài ra, sẽ là bất thường khi sử dụng git commit bên trong --index-filter
.
Bạn đang đối phó với nhiều vấn đề độc lập ở đây.
Chỉ định ngày khác Khác
Mỗi cam kết có hai ngày: ngày tác giả và ngày ủy viên. Bạn có thể ghi đè từng giá trị bằng cách cung cấp các giá trị thông qua các biến môi trường GIT_AUTHOR_DATE và GIT_COMMITTER_DATE cho bất kỳ lệnh nào ghi một cam kết mới. Xem Định dạng ngày của Nhật Bản trong phần git-commit (1) hoặc bên dưới:
Git internal format = <unix timestamp> <time zone offset>, e.g. 1112926393 +0200
RFC 2822 = e.g. Thu, 07 Apr 2005 22:13:13 +0200
ISO 8601 = e.g. 2005-04-07T22:13:13
Lệnh duy nhất viết một cam kết mới trong quá trình sử dụng bình thường là git commit . Nó cũng có một --date
tùy chọn cho phép bạn trực tiếp chỉ định ngày tác giả. Việc sử dụng được dự đoán của bạn git filter-branch --env-filter
cũng bao gồm sử dụng các biến môi trường được đề cập ở trên (đây là một phần của phần mềm env, sau đó tùy chọn này được đặt tên; xem Tùy chọn Tùy chọn trong git-filter-Branch (1) và lệnh git-commit bên dưới -tree (1) .
Chèn một tệp vào một lịch sử ref
Nếu kho lưu trữ của bạn rất đơn giản (tức là bạn chỉ có một nhánh duy nhất, không có thẻ), thì có lẽ bạn có thể sử dụng git rebase để thực hiện công việc.
Trong các lệnh sau, sử dụng tên đối tượng (hàm băm SHA-1) của cam kết thay vì xóa A. Đừng quên sử dụng một trong các phương thức ghi đè lên ngày của Mt khi bạn chạy cam kết git .
---A---B---C---o---o---o master
git checkout master
git checkout A~0
git add path/to/file
git commit --date='whenever'
git tag ,new-commit -m'delete me later'
git checkout -
git rebase --onto ,new-commit A
git tag -d ,new-commit
---A---N (was ",new-commit", but we delete the tag)
\
B'---C'---o---o---o master
Nếu bạn muốn cập nhật A để bao gồm tệp mới (thay vì tạo một cam kết mới ở nơi nó được thêm vào), thì hãy sử dụng git commit --amend
thay vì git commit
. Kết quả sẽ như thế này:
---A'---B'---C'---o---o---o master
Ở trên hoạt động miễn là bạn có thể đặt tên cho cam kết nên là cha mẹ của cam kết mới của bạn. Nếu bạn thực sự muốn tập tin mới của bạn được thêm vào thông qua một cam kết gốc mới (không có cha mẹ), thì bạn cần một cái gì đó hơi khác một chút:
B---C---o---o---o master
git checkout master
git checkout --orphan new-root
git rm -rf .
git add path/to/file
GIT_AUTHOR_DATE='whenever' git commit
git checkout -
git rebase --root --onto new-root
git branch -d new-root
N (was new-root, but we deleted it)
\
B'---C'---o---o---o master
git checkout --orphan
là tương đối mới (Git 1.7.2), nhưng có nhiều cách khác để làm điều tương tự hoạt động trên các phiên bản Git cũ hơn.
Chèn một tập tin vào một Multi- ref Lịch sử
Nếu kho lưu trữ của bạn phức tạp hơn (nghĩa là nó có nhiều hơn một ref (nhánh, thẻ, v.v.)), thì có lẽ bạn sẽ cần phải sử dụng nhánh lọc git . Trước khi sử dụng nhánh lọc git , bạn nên tạo một bản sao lưu toàn bộ kho lưu trữ của mình. Một kho lưu trữ tar đơn giản của toàn bộ cây làm việc của bạn (bao gồm thư mục .git) là đủ. nhánh bộ lọc git thực hiện sao lưu dự phòng, nhưng thường dễ phục hồi hơn từ bộ lọc không hoàn toàn đúng bằng cách xóa.git
thư mục và khôi phục nó khỏi bản sao lưu của bạn.
Lưu ý: Các ví dụ dưới đây sử dụng lệnh cấp thấp hơn git update-index --add
thay vì git add
. Bạn có thể sử dụng git add , nhưng trước tiên bạn cần sao chép tệp từ một số vị trí bên ngoài sang đường dẫn dự kiến ( --index-filter
chạy lệnh của nó trong GIT_WORK_TREE tạm thời trống).
Nếu bạn muốn tệp mới của mình được thêm vào mỗi cam kết hiện có, thì bạn có thể làm điều này:
new_file=$(git hash-object -w path/to/file)
git filter-branch \
--index-filter \
'git update-index --add --cacheinfo 100644 '"$new_file"' path/to/file' \
--tag-name-filter cat \
-- --all
git reset --hard
Tôi thực sự không thấy bất kỳ lý do nào để thay đổi ngày của các cam kết hiện có --env-filter 'GIT_AUTHOR_DATE=…'
. Nếu bạn đã sử dụng nó, bạn sẽ làm cho nó có điều kiện để nó sẽ viết lại ngày cho mỗi cam kết.
Nếu bạn muốn tập tin mới của mình chỉ xuất hiện trong các xác nhận sau một số cam kết hiện có (BẠCH A), thì bạn có thể làm điều này:
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
file_blob=$(git hash-object -w "$file_path")
git filter-branch \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$before_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
Nếu bạn muốn tệp được thêm thông qua một cam kết mới sẽ được chèn vào giữa lịch sử của bạn, thì bạn sẽ cần phải tạo cam kết mới trước khi sử dụng nhánh bộ lọc git và thêm --parent-filter
vào nhánh bộ lọc git :
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
git checkout master
git checkout "$before_commit"
git add "$file_path"
git commit --date='whenever'
new_commit=$(git rev-parse --verify HEAD)
file_blob=$(git rev-parse --verify HEAD:"$file_path")
git checkout -
git filter-branch \
--parent-filter "sed -e s/$before_commit/$new_commit/g" \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$new_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
Bạn cũng có thể sắp xếp để tập tin được thêm vào lần đầu tiên trong một cam kết gốc mới: tạo ra cam kết gốc mới của bạn thông qua phương thức mồ côi mồ côi từ phần git rebase (bắt nó vào new_commit
), sử dụng vô điều kiện --index-filter
và --parent-filter
tương tự "sed -e \"s/^$/-p $new_commit/\""
.