Split Git Shortcomings into new chapter, added to it
[gitmagic/gitmagic.git] / drawbacks.txt
blobee27303abe5e6258a8228e1f19c8dbfdd1857d8f
1 == Git Shortcomings ==
3 There are some Git issues I've swept under the carpet until now. Some can be handled easily with scripts, others require reorganizing or redefining the project, and as for Windows annoyances, one will just have to wait. Or better yet, pitch in and help!
5 === Microsoft Windows ===
7 Git on Microsoft Windows can be cumbersome. It works with Cygwin installed, though is slower. There is also the less invasive http://repo.or.cz/w/git/mingw.git[mingw port] which can be run from the Windows command-line.
9 === Unrelated Files ===
11 If your project is very large and contains many unrelated files that are constantly being changed, Git may be disadvantaged more than other systems because single files are not tracked. Git tracks changes to the whole project, which is usually beneficial.
13 A solution is to break up your project into pieces, each consisting of related files. Use *git submodule* if you still want to keep everything in a single repository.
15 === Diffs ===
17 Some version control systems force you to explicitly tag a file before editing. While this is especially annoying when this tagging involves talking to a central server, it does have two benefits:
19   1. Diffs are quick because only the tagged files need be examined.
21   2. When a central server stores the tags, one can discover who else is working on the file.
23 However, with appropriate scripting, you can achieve the same with Git, though it does require cooperation from the programmer, who should execute particular scripts when editing a file.
25 === File History ===
27 Since Git records project-wide changes, reconstructing the history of a single file requires more work than in version control systems that track individual files. However, the penalty is slight.
29 === Initial Clone ===
31 Creating a clone is more expensive than checking out code in other version control systems when there is a lot of history.
33 The initial payment is worth it in the long run, as most operations will then be fast and offline. However, if the down payment is prohibitive, create a shallow clone with the \--depth option. This is much faster, but the resulting clone has fewer capabilities.
35 === Volatile Projects ===
37 Git was written to be fast with respect to the size of the changes. Humans make small edits from version to version. A one-liner bugfix here, a new feature there, emended comments, that sort of thing. But if you're mostly keeping files that are radically different in successive revisions, on each commit, your history necessarily grows by the size of your whole project.
39 There is nothing any version control system can do about this, but standard Git users will suffer more since normally histories are cloned.
41 The reasons why the changes are so great should be examined. Perhaps file formats should be changed. Minor edits should only cause minor changes to at most a few files.
43 Or perhaps a database or backup/archival solution is what is actually being sought, not a version control system. For example, version control may not be suitable for managing photos periodically taken from a webcam. Again, version control is meant for keeping track of alterations made by humans.
45 If the files really must be constantly morphing and they really must be versioned, a possibility is to use Git in a centralized fashion. One can create shallow clones, which checks out little or no history of the project. Of course, many Git tools will be unavailable, and fixes must be submitted as patches. This is probably fine as it's unclear why anyone would want the history of wildly unstable files.
47 Another example is a project depending on firmware, which takes the form of a huge binary file. The history of the firmware is uninteresting to users, and updates compress poorly, so firmware revisions would unnecessarily blow up the size of the repository.
49 In this case, the source code should be stored in a Git repository, and the binary file should be kept separately. To make life easier, one could distribute a script that uses Git to checkout the code, and rsync for the firmware.
51 === Global Counter ===
53 Some centralized version control systems maintain a positive integer that increases when a new commit is accepted. Git refers to changes by their hash, which is better in many circumstances.
55 But some people like having this integer around. Luckily, it's easy to write scripts so that with every update, the central Git repository increments an integer, perhaps in a tag, and associates it with the hash of the latest commit.
57 Every clone could maintain such a counter, but this would probably be useless, since only the central repository and its counter matters to everyone.
59 === Empty Subdirectories ===
61 Empty subdirectories cannot be tracked. Create dummy files to work around this problem.
63 The current implementation of Git, rather than its design, is to blame for this drawback. With luck, once Git gains more traction, more users will clamour for this feature and it will be implemented.
65 === Initial Commit ===
67 A stereotypical computer scientist counts from 0, rather than 1. Unfortunately, git does not, and many commands are unfriendly before the initial commit. Aside from decreased usability, some corner cases must be handled specially, such as rebasing a branch with a different initial commit.
69 Git would benefit from defining the zero commit: as soon as a repository is constructed, HEAD would be set to the string consisting of 20 zero bytes. This special commit represents an empty tree, with no parent, at a time that predates all other Git repositories.
71 Then running git log, for example, would inform the user that no commits have been made yet, instead of exiting with a fatal error. Similarly for other tools.
73 Every initial commit is implicitly a descendant of this zero commit, so for example, rebasing an unrelated branch would cause the whole branch to be grafted on to the target. Currently, all but the initial commit is applied, resulting in a merge conflict.