开发者

Why are there so many identical executables of git when compiled from source?

git                       
git-add                   
git-annotate              
git-apply                 
git-archive               
git-bisect--helper        
git-blame                 
git-branch                
git-bundle                
git-cat-file              
git-check-attr            
git-checkout              
git-checkout-index        
git-check-ref-format      
git-cherry                
git-cherry-pick           
git-clean                 
git-clone                 
git-commit                
git-commit-tree           
git-config                
git-count-objects         
git-describe              
git-diff                  
git-diff-files            
git-diff-index            
git-diff-tree             
git-fast-export           
git-fetch                 
git-fetch-pack            
git-fmt-merge-msg         
git-for-each-ref          
git-format-patch          
git-fsck                  
git-fsck-objects          
git-gc                    
git-get-tar-commit-id     
git-grep                  
git-hash-object           
git-help                  
git-index-pack            
git-init                  
git-init-db               
git-log                   
git-ls-files              
git-ls-remote             
git-ls-tree               
git-mailinfo              
git-mailsplit             
git-merge                 
git-merge-base            
git-merge-file            
git-merge-index           
git-merge-ours            
git-merge-recursive       
git-merge-subtree         
git-merge-tree            
git-mktag                 
git-mktree                
git-mv                    
git-name-rev              
git-notes                 
git-pack-objects          
git-pack-redundant        
git-pack-refs             
git-patch-id              
git-peek-remote           
git-prune                 
git-prune-packed          
git-push                  
git-read-tree             
git-receive-pack          
git-reflog                
git-remote                
git-remote-ext            
git-remote-fd             
git-replace               
git-repo-config           
git-rerere                
git-reset                 
git-revert                
git-rev-list              
git-rev-parse             
git-rm                    
git-send-pack             
git-shortlog              
git-show                  
git-show-branch           
git-show-ref              
git-stage                 
git-status                
git-stripspace            
git-symbolic-ref          
git-tag                   
git-tar-tree              
git-unpack-file           
git-unpack-objects        
git-update-index          
git-update-ref            
git-update-server-info    
git-upload-archive        
git-var                   
git-verify-pack           
git-verify-tag            
git-whatchanged           
git-write-tree            

All these targets are of the same size: 4951925, and their contents are identical.Why?

[root@ git-1.7.6]$ ls -il /usr/bin/git*
17823222 lrwxrwxrwx 1 root root 22 2011-01-24 11:43 /usr/bin/git -> /usr/local/git/bin/git
17823223 lrwxrwxrwx 1 root root 32 2011-01-24 11:43 /usr/bin/git-cvsserver -> /usr/local/git/bin/git-cvsserver
17823224 lrwxrwxrwx 1 root root 23 2011-01-24 11:43 /usr/bin/gitk -> /usr/local/git/bin/gitk
17823225 lrwxrwxrwx 1 root root 35 2011-01-24 11:43 /usr/bin/git-receive-pack -> /usr/local/git/bin/git-receive-pack
17823226 lrwxrwxrwx 1 root root 28 2011-01-24 11:43 /usr/bin/git-shell -> /usr/local/git/bin/git-shell
17823227 lrwxrwxrwx 1 root root 37 2011-01-24 11:43 /usr/bin/git-upload-archive -> /usr/local/git/bin/git-upload-archive
17823228 lrwxrwxrwx 1 root root 34 2011-01-24 11:43 /usr/bin/git-upload-pack -> /usr/local/git/bin/git-upload-pack



[root@ git-1.7.6]$ ls -li /usr/local/git/bin/git*
126612251 -rwxr-xr-x 107 root root 4686039 2011-01-24 11:42 /usr/local/git/bin/git
126614976 -rwxr-xr-x   2 root root  120960 2011-01-24 11:42 /usr/local/git/bin/git-cvsserver
126614978 -rwxr-xr-x   1 root root  321995 2011-01-24 11:42 /usr/local/git/bin/gitk
126612开发者_运维百科251 -rwxr-xr-x 107 root root 4686039 2011-01-24 11:42 /usr/local/git/bin/git-receive-pack
126612255 -rwxr-xr-x   2 root root 1952607 2011-01-24 11:42 /usr/local/git/bin/git-shell
126612251 -rwxr-xr-x 107 root root 4686039 2011-01-24 11:42 /usr/local/git/bin/git-upload-archive
126612252 -rwxr-xr-x   2 root root 2001993 2011-01-24 11:42 /usr/local/git/bin/git-upload-pack


I think this is being done for backward compatibility since in earlier versions of git, each git subcommand was a separate executable ( for example git-commit instead of git commit )

In later versions they made them actual subcommands with the only real executable being git. The others may just be links to the git executable.


Because the only real command is git. The rest are either symbolically linked to git itself, or (more likely) they're all hard linked.

When two files are hard linked together they reference one copy on disk, albeit with different names. File names are just pointers to a particular inode on disk, which is how Linux/Unix keeps track of what is stored where.

You can verify this by doing:

$ ls -il /usr/bin/git*

If they all share the same number in the first column, then they're all referencing the same inode. The number just after the permissions is the number of hard links to that single inode. The actual disk space for that executable (or any hardlinked file) is not let go until that count reaches zero (all references to it go away).

(BTW... if they're symbolically linked you'll see something like git-annotate -> git which means that the name of git-annotate references the name git which is then resolved to the inode which contains (a pointer to) the data of the executable)

Git itself is one program which knows how to do many things based on how it is called. You can call either git annotate or git-annotate and they'll both will be interpreted by the one git binary to do the annotate operation.

The reason this is done is just for your convenience, there's nothing that git itself needs as you can always use the git<space>command form of its invocation.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜