使用 git 版本控制系统锁定二进制文件

一年半以来,我一直在关注 git 社区,希望能从 SVN 转变过来。阻碍我的一个特殊问题是无法锁定二进制文件。在过去的一年里,我还没有看到这个问题的进展。我明白锁定文件违背了分布式源代码控制的基本原则,但我不认为一个 web 开发公司可以利用 git 来跟踪源代码和图像文件的变化,当存在二进制文件冲突的可能性时。

为了实现锁定的效果,必须标识一个“中心”存储库。不管 git 的分布式特性如何,大多数公司都会为软件项目建立一个“中心”存储库。我们应该能够将一个文件标记为需要在指定地址从管理 git 存储库锁定。也许这很困难,因为 git 跟踪文件内容而不是文件?

你们有没有处理 git 和二进制文件的经验,这些文件在修改之前应该被锁定?

注意: 看起来 Source Gear 的新开源分布式版本控制项目 Veracity 将锁定作为其目标之一。

50542 次浏览

I would not expect file-locking to ever make it as a feature in git. What kind of binary files are you primarily interested in? Are you actually interested in locking the files, or just preventing conflicts caused by not being able to merge them.

I seem to remember someone talking (or even implementing) support for merging OpenOffice-documents in git.

It's worth examining your current workflow to see if locking images is really necessary. It's relatively unusual for two people to independently edit an image, and a bit of communication can go a long way.

I agree that locking binary files is a necessary feature for some environments. I just had a thought about how to implement this, though:

  • Have a way of marking a file as "needs-lock" (like the "svn:needs-lock" property).
  • On checkout, git would mark such a file as read-only.
  • A new command git-lock would contact a central lock server running somewhere to ask permission to lock.
  • If the lock server grants permission, mark the file read-write.
  • git-add would inform the lock server of the content hash of the locked file.
  • The lock server would watch for that content hash to appear in a commit on the master repository.
  • When the hash appears, release the lock.

This is very much a half-baked idea and there are potential holes everywhere. It also goes against the spirit of git, yet it can certainly be useful in some contexts.

Within a particular organisation, this sort of thing could perhaps be built using a suitable combination of script wrappers and commit hooks.

When I was using Subversion, I religiously set the svn:needs-lock property on all binary and even the hard-to-edit text files. I never actually experienced any conflicts.

Now, in Git, I don't worry about such things. Remember: locks in Subversion aren't actually mandatory locks, they are merely communication tools. And guess what: I don't need Subversion to communicate, I can manage just fine with E-Mail, Phone and IM.

Another thing I did, is to replace many binary formats with plain text formats. I use reStructuredText or LaΤΕΧ instead of Word, CSV instead of Excel, ASCII-Art instead of Visio, YAML instead of databases, SVG instead of OO Draw, abc instead of MIDI, and so on.

We've just recently started using Git (used Subversion previously) and I have found a change to workflow that might help with your problem, without the need for locks. It takes advantage of how git is designed and how easy branches are.

Basically, it boils down to pushing to a non-master branch, doing a review of that branch, and then merging into the master branch (or whichever the target branch is).

The way git is "intended" to be used, each developer publishes their own public repository, which they request others to pull from. I've found that Subversion users have trouble with that. So, instead, we push to branch trees in the central repository, with each user having their own branch tree. For instance, a hierarchy like this might work:

users/a/feature1
users/a/feature2
users/b/feature3
teams/d/featurey

Feel free to use your own structure. Note I'm also showing topic branches, another common git idiom.

Then in a local repo for user a:

feature1
feature2

And to get it to central server (origin):

git push origin feature1:users/a/feature1

(this can probably be simplified with configuration changes)

Anyway, once feature1 is reviewed, whomever is responsible (in our case, it's the developer of the feature, you could have a single user responsible for merges to master), does the following:

git checkout master
git pull
git merge users/name/feature1
git push

The pull does a fetch (pulling any new master changes and the feature branch) and the updates master to what the central repository has. If user a did their job and tracked master properly, there should be no problems with the merge.

All this means that, even if a user or remote team makes a change to a binary resource, it gets reviewed before it gets incorporated into the master branch. And there is a clear delineation (based on process) as to when something goes into the master branch.

You can also programmatically enforce aspects of this using git hooks, but again, I've not worked with these yet, so can't speak on them.

I have discussed this issue on git discussion groups and have concluded that at this time, there is no agreed upon method of centralized file locking for git.

In response to Mario's additional concern with changes happening in multiple places on the binaries. So the scenario is Alice and Bob are both making changes to the same binary resource at the same time. They each have their own local repo, cloned from one central remote.

This is indeed a potential problem. So Alice finishes first and pushes to the central alice/update branch. Normally when this happens, Alice would make an announcement that it should be reviewed. Bob sees that and reviews it. He can either (1) incorporate those changes himself into his version (branching from alice/update and making his changes to that) or (2) publish his own changes to bob/update. Again, he makes an announcement.

Now, if Alice pushes to master instead, Bob has a dilemma when he pulls master and tries to merge into his local branch. His conflicts with Alice's. But again, the same procedure can apply, just on different branches. And even if Bob ignores all the warnings and commits over Alice's, it's always possible to pull out Alice's commit to fix things. This becomes simply a communication issue.

Since (AFAIK) the Subversion locks are just advisory, an e-mail or instant message could serve the same purpose. But even if you don't do that, Git lets you fix it.

No, there's no locking mechanism per se. But a locking mechanism tends to just be a substitute for good communication. I believe that's why the Git developers haven't added a locking mechanism.

Subversion has locks, and they aren't just advisory. They can be enforced using the svn:needs-lock attribute (but can also be deliberately broken if necessary). It's the right solution for managing non-mergeable files. The company I work for stores just about everything in Subversion, and uses svn:needs-lock for all non-mergeable files.

I disagree with "locks are just a communication method". They are a much more effective method than push-notifications such as phone or e-mail. Subversion locks are self-documenting (who has the lock). On the other hand, if you have to communicate by other traditional push-notification channels, such as e-mail, who do you send the notification to? You don't know in advance who might want to edit the file, especially on open-source projects, unless you have a complete list of your entire development team. So those traditional communication methods aren't nearly as effective.

A central lock server, while against the principles of DVCS, is the only feasible method for non-mergeable files. As long as DVCS don't have a central lock feature, I think it will keep the company I work for using Subversion.

The better solution would be to make a merge tool for all your binary file formats, but that's a longer-term and ongoing goal that will never be "finished".

Here's an interesting read on the topic.

What about cad files? If the files aren't locked, to be kept read-only as well, most cad programms would just open them an change arbitrary bits, seen as a new file by any vcs. So in my view, locking is an ideal means for communicating your intend to change some particalur file. As well, it prevents some Software to gain write access in the first place. This allows updates of the local files, without the need to close the software or at least all files entirely.

Im not suggesting to use git at my company for the same problem. We use EA for all our designs and microsoft word for documentation, we don't know in advance who may edit a particular file so exclusive locking is our only option.

git will work very well in a non-team environment where each developer is solely responsible for a piece of code or file, because in that case communication about locks is not needed.

If your organization requires team environment (usually to strip developers from job security), then use svn, git is not for you. Svn provides both - source control and communication between developers about locks.

Just put a text file in cc with the file that you want to lock and then have the update hook reject it.

TortoiseGit supports full git workflow for Office documents delegating diff to Office itself. It works also delegating to OpenOffice for OpenDocument formats.

Git is not providing any command to lock files but I've fund a way to achieve that function using git hooks. An auxiliary server is needed to store the lock informations. We can use a pre-commit hook to check if any of the committed files is locked. And if anyone locks a file, a program should tell the auxiliary server the information of the locker and the locked file.

It might be true, that reorganising a project can help avoiding locks, but:

  • Teams are also organised by other priorities (location, customers, ...)
  • Tools are also selected by other targets (compatibility, price, ease of use by most of the employees)
  • Some tools (and therefore there binary files) cannot be avoided, as there is simply no replacement that can do the same job, fitting the same to the companys needs for the same price.

To request, that a whole company might reorganise their workflow and replace all their tools that produce binaries, only to be able to work with git, because of the lack of locks, sounds quite inefficient.

Locks do not fit into the git philosophy (which was never made for binaries), but there are non-neglectable situations, where locks are the most efficient way to solve such a problem.

This is not a solution but rather a comment on why locking mechanisms are needed. There are some tools used in some fields which use binary only formats which are flat out mission critical and the "use better/different tools" is just not an option. There are no viable alternate tools. The ones I'm familiar with really wouldn't be candidates for merging even if you stored the same information in an ascii format. One objection I've heard is that you want to be able to work offline. The particular tool I'm thinking of really doesn't work offline anyway because of needing to pull licenses so if I have data on a laptop it isn't like I can run the tool while on a train anyway. That said, what git does provide if I have a slow connection, I can get licenses and also pull down changes but have the fast local copy for looking at different versions. That is a nice thing that the DVCS gives you even in this case.

One view point is that git is simply not the tool to use but it is nice for all the text files which are also managed with it and it is annoying to need different version control tools for different files.

The sort-of-advisory-locking-via-mail approach really stinks. I've seen that and have been tired of an endless stream of emails of "I'm editing it" "I'm done editing" and seen changes lost because of it. The particular case I'm thinking of was one where a collection of smaller ascii files would have been much nicer but that is an aside.

Git LFS 2.0 has added support for file locking.

With Git LFS 2.0.0 you can now lock files that you're actively working on, preventing others from pushing to the Git LFS server until you unlock the files again.

This will prevent merge conflicts as well as lost work on non-mergeable files at the filesystem level. While it may seem to contradict the distributed and parallel nature of Git, file locking is an important part of many software development workflows—particularly for larger teams working with binary assets.