2009-01-07 158 views
129

我想使用git來記錄對文件的所有更改。使git自動提交

有沒有辦法讓git'commit'在每次文件更新時自動發生 - 所以每次文件更改都有一個新的提交?

理想情況下,我希望我的用戶甚至不知道git在幕後運行。然後,用戶可能會「撤消」對文件的更改 - 這可以通過從git中提取以前的版本來實現。

+6

使用版本控制文件系統會更容易:http://en.wikipedia.org/wiki/Versioning_file_system – 2012-10-16 17:42:09

+1

SparkleShare在這方面相當令人印象深刻。 – theode 2017-03-23 16:41:32

回答

102

在Linux上,您可以使用inotifywait在每次更改文件內容時自動執行命令。

編輯:下面的命令,只要它被保存提交file.txt的:

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

如何讓它爲整個文件夾執行此操作(不只是單個文件?) – 2012-10-28 23:48:56

+1

對`inotifywait`使用`-r`標誌,但請注意,內核對可設置的inotifywait監視的數量有限制向上。 `人inotifywait`會告訴你更多。 – JesperE 2012-10-29 09:22:17

+9

在Windows中有沒有任何選項..? – 2013-12-09 12:29:22

1

我敢肯定,你需要將其掛接到用戶正在使用的任何編輯器中。您可以編寫一些內容來輪詢更改,但根據使用模式的不同,輪詢頻率可能需要非常高才能確保它正在收集單個更改而不是多次更改。

+0

另外,對更改進行輪詢會創建競爭條件。 – Bombe 2009-01-07 12:49:16

+1

不適用於像emacs和yi這樣的編輯器,它們通過「事務性」寫入文件來確保數據在崩潰後不會丟失。 – 2011-07-05 08:12:04

2

如果知道該文件的名稱和要監視只有一個(或幾個文件),可以每隔幾分鐘簡單地調用一次「git commit」來實現此目的。如果文件沒有改變,git只會抱怨,你必須忽略這個錯誤,但除此之外,不會有任何損壞。

除此之外,您還需要將這些文件標記爲「自動提交」,以便能夠手動提交。通過這種方式,用戶可以看到自動更改以及更大的「邏輯」更改,這些更改伴隨着提交註釋,以解釋自上次手動提交以來發生的更改。

例如,使用「AUTOCOMMIT」作爲提交消息。之後,你可以編寫一個工具來使用git log來清除這些提交(找出要修改的kill),或者你可以嘗試使用暴力衝突解決策略創建一個分支AUTOCOMMIT來敲擊「手動提交」。

另一種選擇是使用git低級命令來構建自己的專用存儲庫。

最後,您可以在執行自動提交以區分手動版本和自動版本時,將文件複製到新名稱(「$ filename.ac」)。

42

早些時候inotifywait答案很好,但它不是一個完全的解決方案。正如所寫的,它是一次性提交文件中的一次更改。它不適用於編輯文件時使用原始名稱創建新的inode的常見情況。 inotifywait -m顯然是按照inode而不是按名稱的文件。此外,文件更改後,它不會git commit沒有git addgit commit -a。進行一些調整,這裏是我在Debian上用來跟蹤日曆文件的所有更改:

/etc/rc。本地:


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

/家庭/ <用戶名> /斌/ 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 

這可以推廣到等待文件和/或目錄,以及相應的inotifywait進程的列表上,並在文件更改時重啓每個inotifywait

1

我有同樣的問題,並在mac launchd提供了一個很好的解決方案。 它會看文件或目錄,如果有變化,你可以運行一個應用程序或其他任何東西...

14

git-wip是一個很好的解決方案,適合我。 「在製品」代表「工作進行中」。每次運行'git wip'時,都會將這些更改提交給一個單獨的分支。它可以在命令行上運行,但是vim和emacs的擴展可以在每次寫入文件時自動運行git-wip。

5

我寫了一個程序,GitPrime,爲您的本地Git存儲庫提供自動保存。現在很容易回滾到你破壞之前! Bitbucket repository

這應該適用於任何支持bash shell(包括Windows + Cygwin)的平臺。

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

使用當前日期和時間自動推送。

7

Inotify確實聽起來像是正確的工具。

有一個工具叫incron這可能正是你在找什麼。你可以在類似crontab的東西中指定文件或文件夾(和事件類型,如「更改」,「創建」,「取消鏈接」),以及在發生此類事件時運行的命令。

與inotifywait(這可能是窮人的cron sleep 10;do stuff的模擬)相反,這將捕獲每個事件,而不僅僅是第一個事件。

我自己並沒有使用它,但從文檔看起來它看起來不太複雜。

21

前面的回答推薦inotifywait這個工作讓我在正確的方向上提供了自己的問題,所以我寫了一個小腳本。首先,這隻能遞歸地觀察整個文件夾(與Lester Buck的例子相反),但之後我還想在別的地方觀看文件,所以我擴展了它。

結果是腳本目前所謂gitwatch,因爲這是它做什麼:這手錶更改(使用inotifywait)的文件或文件夾,並承諾遵守一個Git倉庫。

你可以找到腳本,詳細信息和說明了在GitHub上:https://github.com/nevik/gitwatch

10

我想這樣做的窗戶,發現最好的辦法是使用Directory Monitor檢查更改,然後當它檢測到變化讓它運行:

程序:cmd。EXE

PARAMS:/CC:\pathToBatchFile.bat

該批處理文件包含:

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

我也試過在那裏有另一個命令添加文件("%PROGRAMFILES(X86)%\git\bin\sh.exe" --login -i -c "git add *.*"),但我不我認爲我的工作正常。

我還做了一個包含post-commit鉤子:

#!/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 

(如果有任何衝突,那麼它會中止拉動和中止推,但沒有任何明確的方式告訴了發生 - 最後我們放棄了整個想法,因爲這個缺陷。)

curl命令告訴我的服務器它需要對代碼進行拉取。所有這一切都需要處理它是PHP:

<? 
$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"; 
} 
?> 

與唯一的問題是它需要root用戶,而不是apache用戶運行的,所以我也不得不做出一個文件中/etc/sudoers.d/含:

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

對我來說,我認爲這個工作非常紮實。目錄監視器可以配置爲在啓動時運行並開始最小化,並且它可以觀看幾個不同的文件夾

1

聽起來好像您正在尋找類似於etckeeper的東西,它旨在自動檢查您的所有變更到/ etc/*到git中(或者你想要的任何VCS),但是我沒有看到它不能用於除/ etc之外的其他文件。

如果你只想處理一個單一的文件,也許這不完美,但如果你想跟蹤給定目錄中的所有內容,我認爲這是值得的。

1

當用戶更改文件時,該腳本不運行,但它可以作爲cron作業運行(通過將其放入/etc/cron.*目錄中),這也是一個合理的解決方案。

此腳本將遍歷/ srv/www目錄(將其更改爲所有站點的存儲位置),添加,提交和推送所有文件,並將所有文件記錄到/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 
4

如果有人試圖從Powershell的做到這一點我使用下面的獲得了成功:

& "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"