Tạo git tự động cam kết


154

Tôi muốn sử dụng git để ghi lại tất cả các thay đổi vào một tệp.

Có cách nào để tôi có thể bật git 'commit' để tự động xảy ra mỗi khi tệp được cập nhật - vì vậy có một cam kết mới cho mỗi thay đổi đối với tệp không?

Lý tưởng nhất là tôi muốn người dùng của mình thậm chí không biết rằng git đang chạy phía sau hậu trường. Sau đó, một người dùng có thể có khả năng "hoàn tác" các thay đổi đối với tệp - và điều này có thể đạt được bằng cách rút phiên bản trước đó ra khỏi git.


9
Sẽ dễ dàng hơn khi sử dụng hệ thống tập tin phiên bản: en.wikipedia.org/wiki/Versioning_file_system
William Pursell

1
SparkleShare khá ấn tượng về điều đó.
theode

SparkleShare có vẻ là một tùy chọn tuyệt vời nhưng nó phá hủy bất kỳ thư mục .git nào bên trong git chính
phù hợp

Bạn có thể sử dụng github.com/jw0k/gwatch . Nó hoạt động trên Windows và Linux.
rubix_addict

@rubix_addict Tại sao bạn không đăng câu trả lời đó?
Tobias Kienzler

Câu trả lời:


127

Trên Linux, bạn có thể sử dụng inotifywait để tự động thực thi lệnh mỗi khi thay đổi nội dung của tệp.

Chỉnh sửa: lệnh sau cam kết file.txt ngay khi được lưu:

inotifywait -q -m -e CLOSE_WRITE --format="git commit -m 'autocommit on change' %w" file.txt | sh

2
Làm thế nào bạn có thể làm cho nó làm điều này cho toàn bộ thư mục (không chỉ một tệp duy nhất?)
Anderson Green

2
Sử dụng -rcờ để inotifywait, nhưng lưu ý rằng kernel có giới hạn về số lượng đồng hồ inotifywait mà nó có thể thiết lập. man inotifywaitsẽ cho bạn biết nhiều hơn
JesperE

14
Có bất kỳ tùy chọn trong windows ..?
Chandan Pasunoori

50

Câu trả lời inotifywait trước đó là tuyệt vời, nhưng nó không phải là một giải pháp hoàn chỉnh. Như đã viết, đó là một cam kết một lần cho một lần thay đổi trong một tệp. Nó không hoạt động trong trường hợp phổ biến khi chỉnh sửa một tệp tạo ra một nút mới với tên gốc. inotifywait -m rõ ràng theo sau các tệp bằng inode, không phải theo tên. Ngoài ra, sau khi tệp đã thay đổi, nó không được phân loại cho git commit mà không có git add hoặc git commit -a . Thực hiện một số điều chỉnh, đây là những gì tôi đang sử dụng trên Debian để theo dõi tất cả các thay đổi đối với tệp lịch của mình:

/etc/rc.local:


su -c /home/<username>/bin/gitwait -l <username>

/ home / <tên người dùng> / bin / gitwait:


#!/bin/bash
#
# gitwait - watch file and git commit all changes as they happen
#

while true; do

  inotifywait -qq -e CLOSE_WRITE ~/.calendar/calendar

  cd ~/.calendar; git commit -a -m 'autocommit on change'

done

Điều này có thể được tổng quát hóa để chờ đợi trong danh sách các tệp và / hoặc thư mục, và các quy trình inotifywait tương ứng và khởi động lại mỗi inotifywait khi một tệp được thay đổi.


8
Lester bạn có thể vui lòng mở rộng về cách khái quát hóa điều này vào một thư mục?
Diego

29

Các câu trả lời trước đây khuyến nghị inotifywait cho công việc này đã đưa tôi đi đúng hướng khi tôi gặp vấn đề này, vì vậy tôi đã viết một kịch bản nhỏ. Đầu tiên, điều này chỉ có thể xem toàn bộ các thư mục theo cách đệ quy (ngược lại với ví dụ của Lester Buck), nhưng sau đó tôi cũng muốn xem một tệp ở một nơi khác, vì vậy tôi đã mở rộng nó.

Kết quả là một tập lệnh hiện đang được gọi gitwatch, vì đó là những gì nó làm: nó xem một tập tin hoặc thư mục để thay đổi (sử dụng inotifywait) và cam kết chúng vào một kho lưu trữ git.

Bạn có thể tìm thấy tập lệnh, thêm thông tin và hướng dẫn trên github: https://github.com/nevik/gitwatch


4
kịch bản nhỏ hữu ích đó. Tôi sẽ ghi chú về nó.
iwein

thú vị có thể hữu ích cho các trang web magento. Tôi đang thử nghiệm nhưng dường như cũng không thể khiến nó tự động đẩy
NoSixies

16

git-wip là một giải pháp tuyệt vời phù hợp với tôi. "WIP" là viết tắt của "công việc đang tiến triển". Mỗi khi bạn chạy 'git wip', các thay đổi được cam kết thành một nhánh riêng. Nó có thể được chạy trên dòng lệnh, nhưng có phần mở rộng cho vim và emacs để tự động chạy git-wip mỗi khi tệp được ghi.


12

Tôi muốn làm điều này trong các cửa sổ và tìm thấy cách tốt nhất là sử dụng Directory Monitor để kiểm tra các thay đổi sau đó khi phát hiện ra một thay đổi, nó sẽ chạy:

Chương trình: cmd.exe

Params: /CC:\pathToBatchFile.bat

Tập tin đó chứa:

c:
cd c:\gitRepoDirectory\
(if exist "%PROGRAMFILES(X86)%" (
"%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git commit -am AutoCommitMessage"
) else (
"%PROGRAMFILES%\git\bin\sh.exe" --login -i -c "git commit -am AutoCommitMessage"
))

Tôi cũng đã thử có một lệnh khác trong đó để thêm tệp ( "%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git add *.*"), nhưng tôi không nghĩ rằng tôi đã làm cho nó hoạt động đúng.

Tôi cũng đã thực hiện một hook hook sau:

#!/bin/sh
git.exe pull -v --progress  "origin"
git.exe push    --progress  "origin" master:master
curl.exe -s https://webserverdomain.com/updateFromGitHook.x?r=repoName

(Nếu có bất kỳ xung đột nào thì nó sẽ hủy bỏ lực kéo và hủy bỏ lực đẩy, nhưng không có cách nào rõ ràng để nói rằng điều đó đã xảy ra - cuối cùng chúng tôi đã từ bỏ toàn bộ ý tưởng vì lỗi này.)

Lệnh curl đó nói với máy chủ của tôi rằng nó cần thực hiện thao tác kéo mã. Tất cả những gì cần thiết để xử lý nó trong php là:

<?
$r = $_GET['r'];
if (!empty($c)) {
    //use system instead of exec if you want the output to go back to the git client
    exec("cd /path/to/repo/parent/$r; sudo git reset --hard HEAD; sudo git pull;");
    echo "\n\nServer: Updated\n\n";
} else {
    echo "\n\nServer: UPDATE FAILED\n\n";
}
?>

Vấn đề duy nhất là nó cần được chạy bởi người dùng root thay vì người dùng apache, vì vậy tôi cũng phải tạo một tệp /etc/sudoers.d/có chứa:

www-data ALL = NOPASSWD: /usr/bin/git

Đối với tôi, tôi nghĩ rằng làm việc khá vững chắc. Thư mục màn hình có thể được cấu hình để chạy khi khởi động và bắt đầu thu nhỏ, và nó có thể xem một số thư mục khác nhau


Ngoài ra trên Windows, tôi không thể chạy git trong LocalSystem, vì vậy nếu bạn tạo dịch vụ giám sát của riêng mình, bạn sẽ phải chạy nó dưới một người dùng thực sự có thể chạy Git. Có thể tôi chỉ thiếu một số cài đặt / cấu hình, nhưng có lẽ nó sẽ tốt hơn để thiết lập một tài khoản cam kết git mới
Whelkaholism

8
#!/bin/bash
git commit -a -m "autoupdate `date +%F-%T`"
git push

autopushing với ngày giờ hiện tại.


8

Inotify thực sự nghe có vẻ là công cụ phù hợp cho công việc.

Có một công cụ gọi là incron có thể chính xác là những gì bạn đang tìm kiếm. Bạn có thể chỉ định các tệp hoặc thư mục (và các loại sự kiện, như "thay đổi", "tạo", "hủy liên kết") trong một cái gì đó như crontab và lệnh để chạy khi sự kiện đó xảy ra.

Trái ngược với inotifywait (sẽ tương tự như người bạn thân của người nghèo sleep 10;do stuff), điều này sẽ nắm bắt mọi sự kiện, không chỉ lần đầu tiên.

Tôi đã không sử dụng nó cho mình, nhưng từ tài liệu có vẻ không quá phức tạp để thiết lập.


7

Tôi đã viết một chương trình, GitPrime , để cung cấp tự động lưu trữ cho kho Git cục bộ của bạn. Bây giờ dễ dàng để quay trở lại trước khi bạn phá vỡ nó! Kho lưu trữ bitbucket .

Điều này sẽ hoạt động trên bất kỳ nền tảng nào hỗ trợ bash shell bao gồm Windows + Cygwin.


+1 Tôi đang sử dụng tính năng này trên windows (CygWin) để tự động thay đổi tôi thực hiện với kho lưu trữ git-tf cứ sau 10 phút sử dụng tác vụ theo lịch trình
Darbio

6

Trong trường hợp bất cứ ai cố gắng làm điều này từ Powershell, tôi đã thành công khi sử dụng như sau:

& "C:\Program Files (x86)\Git\bin\sh.exe" -c "cd D:\PATH\TO\REPO && git add --all  &&  git commit -m 'Automatic Commit Message Goes Here' && git push origin master"

5
Và làm thế nào điều này được kích hoạt tự động?
jerik

2
Nhiệm vụ theo lịch trình?
ozzy432836


2

Nếu bạn biết tên của tệp và bạn chỉ muốn theo dõi một (hoặc một vài tệp), bạn chỉ cần gọi "git commit" cứ sau vài phút để đạt được điều này. Nếu tệp không thay đổi, git sẽ chỉ khiếu nại và bạn sẽ phải bỏ qua lỗi này nhưng ngoài ra, sẽ không có tham nhũng.

Ngoài ra, bạn sẽ muốn đánh dấu các tệp này là "tự động cam kết" để có thể cam kết theo cách thủ công. Bằng cách này, người dùng có thể thấy các thay đổi tự động và cả những thay đổi "logic" lớn hơn đi kèm với các nhận xét cam kết để giải thích đã thay đổi kể từ lần cam kết thủ công cuối cùng.

Ví dụ: sử dụng "AUTOCOMMIT" làm thông điệp cam kết. Sau đó, bạn có thể viết một công cụ để xóa các cam kết này bằng cách sử dụng nhật ký git (để tìm ra các sửa đổi để tiêu diệt) hoặc bạn có thể thử tạo một AUTOCOMMIT chi nhánh bằng cách sử dụng chiến lược giải quyết va chạm lực lượng mạnh mẽ để thực hiện "cam kết thủ công".

Một tùy chọn khác là sử dụng các lệnh cấp thấp git để xây dựng kho lưu trữ chuyên dụng của riêng bạn.

Cuối cùng, bạn có thể sao chép tệp sang một tên mới ("$ filename.ac") trong khi thực hiện tự động cam kết để phân biệt giữa phiên bản thủ công và tự động.


1

Tôi khá chắc chắn rằng bạn cần nối nó vào bất kỳ trình soạn thảo nào mà người dùng của bạn đang sử dụng. Bạn có thể viết một cái gì đó để thăm dò các thay đổi, nhưng tùy thuộc vào cách sử dụng, tần suất bỏ phiếu có thể cần phải cực kỳ cao để đảm bảo rằng nó đang chọn các thay đổi riêng lẻ thay vì nhiều thay đổi.


Ngoài ra, bỏ phiếu cho những thay đổi sẽ tạo ra điều kiện chủng tộc.
Bombe

1
Không phải với các biên tập viên như emacs và yi, họ viết các tệp "giao dịch" để cố gắng đảm bảo dữ liệu sẽ không bị mất sau khi gặp sự cố.
Robin Green

1

Nghe có vẻ như bạn đang tìm kiếm thứ gì đó tương tự như etckeeper , được thiết kế để tự động kiểm tra tất cả các thay đổi của bạn thành / etc / * thành git (hoặc bất kỳ VCS nào bạn muốn), nhưng tôi thấy không có lý do gì nó không thể được sử dụng với các tệp khác với những người trong / vv.

Nếu bạn chỉ muốn xử lý một tệp duy nhất, có thể điều đó sẽ không hoàn hảo, nhưng nếu bạn muốn theo dõi mọi thứ trong một thư mục nhất định, tôi nghĩ rằng nó đáng để kiểm tra.


1

Tập lệnh này không chạy khi người dùng thay đổi tệp, nhưng nó có thể được chạy dưới dạng công việc định kỳ (bằng cách thả nó vào thư mục /etc/cron.*), đây cũng là một giải pháp hợp lý.

Tập lệnh này sẽ lặp qua thư mục / srv / www của bạn (thay đổi nó thành bất kỳ nơi nào tất cả các trang web của bạn được lưu trữ), thêm, cam kết và đẩy tất cả các tệp và đăng nhập mọi thứ vào /var/log/gitlog.txt

now=$(date +"%m.%d.%Y_%T")
logfile='/var/log/gitlog.txt'

for dir in /srv/www/*/
do
echo -e '\n' >> $logfile
echo "autocommit $dir $now" >> $logfile
echo "--------------------------" >> $logfile

cd $dir
git add . >> $logfile
git commit -am "autocommit $now" >> $logfile
git push origin master >> $logfile
done

0

tôi đã có cùng một vấn đề và trên mac launchd cung cấp cho bạn một giải pháp tuyệt vời. nó sẽ xem một tập tin hoặc một thư mục và nếu có thay đổi, bạn có thể chạy một ứng dụng hoặc bất cứ thứ gì khác ...


Xem "Giám sát thư mục" tại đây: developer.apple.com/l
Kris


0

Điều này không thỏa mãn phần "Lý tưởng" của câu hỏi, nhưng đây là câu hỏi gần nhất tôi thấy cho câu trả lời tôi muốn, vì vậy tôi đoán rằng nó có thể đi đến đây. Bài viết stackoverflow đầu tiên của tôi mặc dù vậy, xin lỗi nếu tôi nhầm.

Kịch bản sau đây đảm bảo cam kết tự động đối với các thay đổi đã lưu, nhưng không nhắc người dùng nhập cam kết. (Tôi nhận ra kịch bản của mình hơi khác so với git-noob).


# While running, monitors the specified directory, and when a file therein 
# is created or edited and saved, this prompts the user for a commit message.
# The --exclude is to avoid extra prompts for the changes made to 
# version control directories.

# requires inotify-tools

inotifywait --exclude '/\..+' -m  path/to/directory -e modify -e create |
        while read path action file; do
                gnome-terminal -e 'bash -c "cd path/to/directory; 
                                            git add *; 
                                            echo What did you just do??; 
                                            read varname; 
                                            git commit -m \"$varname\""'
        done

0

Cho cửa sổ

Theo bài viết này về autocommit , bạn nên tạo .battệp có nội dung:

git add -u
git commit -m "your commit message"
git push origin master 

và thực hiện với Task Scheduler. Nếu bạn không biết cách làm từng bước một, hãy tham khảo bài viết đó.

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.