2009-01-07 161 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"