CARVIEW |
Contents
-
General Questions
- What is git ?
- Why the 'git' name?
- What's the difference between fetch and pull?
- What can I use to set up a public repository?
- Can I add empty directories?
- Why does git not "track" renames?
- Why is "git log <filename>" slow?
- Why is it wrong to export the environment variable CDPATH?
- How come gitweb suddenly disappeared from the project list at kernel.org/git?
- What is the difference between a merge and a rebase?
- Why is "git rm" not the inverse of "git add"?
-
Features
- Does git convert between CRLF and LF for different platforms?
- Does git have keyword expansion?
- Does git allow arbitrary conversion of contents?
- Does git convert encodings of file names?
- Does git convert encodings of comments and committer names or file content?
- Does git track all file data and metadata?
-
Unexpected behavior
- Why won't I see changes in the remote repo after "git push"?
- Why is git --version not reporting the "full" version number?
- Why is "git reset --hard" not removing some files?
- Why is my push rejected with a non-fast forward error?
- Why won't "git push" work after I rebased a branch?
- Why is "git commit -a" not the default?
- My HTTP repository has updates, which git clone misses. What happened?
- Why isn't Git preserving modification time on files?
- Why does git use a pager for commands like diff/log and --help?
- Why does diff/log not show color, even though I enabled it?
- Why does git diff sometimes list a file that has no changes?
- What does the gitk error message "Can't parse git log output:" mean?
- Why does gitk on Cygwin display "git 1316 tty_list::allocate: No tty allocated"?
- Why does git clone, git pull, etc. fail when run on a partition mounted with sshfs (FUSE)?
- Why does "git bisect" make me test versions outside the "good-bad" range?
- Why am I "not on any branch"?
- "git log -S" does not show all commits
-
How do I ...
- How do I specify what ssh key git should use?
- How do I untrack a file?
- How do I access other branches in a repository?
- How do I share a git public repository and use it in a CVS way?
- How can I add a diff of the commit into the commit message window?
- How would I use "git push" to sync out of a firewalled host?
- How do I check out the tree at a particular tag?
- How to share objects between existing repositories?
- How to stop sharing objects between repositories?
- How do I tell git to ignore files?
- How do I save some local modifications?
- How to manually resolve conflicts when Git failed to detect rename?
- How to revert file to version from current commit?
- How to view an old revision of a file or directory?
- How do I make a diff between two arbitrary files in different revisions?
- How to fix a broken repository?
- How to set up a git server?
- How to create the first project?
- How do I publish my repo via SFTP?
- How do I do a quick clone without history revisions?
- How do I use git for large projects, where the repository is large, say approaching 1 TB, but a checkout is only a few hundred MB? Will every developer need 1 TB of local disk space?
- How do I obtain a list of files which have changed in a given commit?
- How do I remove all the old objects after using filter-branch?
- How do I mirror a SVN repository to git?
- How do I edit the root commit?
- How do I clone a subdirectory?
- How do I make existing non-bare repository bare?
- How do I find large files?
-
Error diagnostic
- Git commit is dying telling me "fatal: empty ident <user@myhost> not allowed", what's wrong?
- Why won't git let me change to a different branch?
- refs/heads/pu: does not fast forward to branch 'pu'
- protocol error: bad line length character
- "unable to chdir or not a git archive" while pushing
- "needs update" and "not uptodate"
- "git-receive-pack: command not found" on push/fetch/pull
- My username contains a '@', I can't clone through HTTP/HTTPS
- Importing from other revision control systems
- References
See also:
General Questions
What is git ?
Git is a distributed version control system developed by Junio Hamano and Linus Torvalds.
Git does not use a centralized server.
Git runs on Linux, BSD, Solaris, Darwin, Windows, Android and other operating systems.
Quoting Linus: "I'm an egotistical ***, and I name all my projects after myself. First 'Linux', now 'git'". ('git' is British slang for "pig headed, think they are always correct, argumentative"). Alternatively, in Linus' own words as the inventor of git: "git" can mean anything, depending on your mood:
The short definition is: Fetch: Download (new) objects and a head from another repository. Pull: Fetch (as defined above), and then merge what was downloaded with the current development. See the git-fetch(1) and git-pull(1) man pages or the tutorials for more details.
A SSH server, an HTTP server, or the git-daemon. Local networks can also use network filesystems, like NFS or SMBFS/CIFS (the Windows networks). See the Git tutorial for more details.
Currently the design of the git index (staging area) only permits files to be listed, and nobody competent enough to make the change to allow empty directories has cared enough about this situation to remedy it. Directories are added automatically when adding files inside them. That is, directories never have to be added to the repository, and are not tracked on their own. You can say "git add <dir>" and it will add files in there. If you really need a directory to exist in checkouts you should create a file in it. .gitignore works well for this purpose (there is also a tool MarkEmptyDirs which allows to automate this task); you can leave it empty, or fill in the names of files you expect to show up in the directory.
Git has to interoperate with a lot of different workflows, for example some changes can come from patches, where rename information may not be available. Relying on explicit rename tracking makes it impossible to merge two trees that have done exactly the same thing, except one did it as a patch (create/delete) and one did it using some other heuristic. On a second note, tracking renames is really just a special case of tracking how content moves in the tree. In some cases, you may instead be interested in querying when a function was added or moved to a different file. By only relying on the ability to recreate this information when needed, Git aims to provide a more flexible way to track how your tree is changing. However, this does not mean that Git has no support for renames. The diff machinery in Git has support for automatically detecting renames, this is turned on by the '-M' switch to the git-diff-* family of commands. The rename detection machinery is used by git-log(1) and git-whatchanged(1), so for example, 'git log -M' will give the commit history with rename information. Git also supports a limited form of merging across renames. The two tools for assigning blame, git-blame(1) and git-annotate(1) both use the automatic rename detection code to track renames. As a very special case, 'git log' version 1.5.3 and later has '--follow' option that allows you to follow renames when given a single path. Mail by Linus on this topic. Git has a rename command git mv, but that is just a convenience. The effect is indistinguishable from removing the file and adding another with different name and the same content.
The answer to the question why git log <filename> takes so long to find a small number of commits which changed a given file lies in the fact that Git looks at all the commits to find that. Git simply does not have per-file history. Not having per-file history is what allows Git to do git log <directory-or-file> rather than being able to track just one file. You can't do it sanely with per-file history (because to tie the per-file histories back together in a logical sequence, you need the global history to sort it again!). That said, you might well need to just run git gc to make it hugely faster. Note that git log <file1> <file2> (or gitk <file1> <file2>) is not simply the union of git log <file1> and git log <file2>; it can contain merges which are in neither of the separate histories. Doing the history for two files together is not at all equivalent to doing the history for those files individually and stitching it together. To speed up git log, give it a range of interesting revisions; you can also try --remove-empty option (with some caveats). Re: how to speed up "git log"? by Linus Torvalds on Git mailing list.
The CDPATH variable is purely for interactive use. A lot of scripts break if a simple "cd" suddenly outputs a text that was directed at you, the user, and not meant for processing by the script. Setting, but not exporting, CDPATH will still work as expected, but may break many scripts, including the make procedure of Git. Having said that, we tried hard to avoid to unset CDPATH everywhere in the Git scripts, and in the Makefiles, but it is well possible that we missed out some places. In contrast, if you just remove the "export" from your .bashrc, you are guaranteed to never get bitten by that breakage again!
Because it got merged into git. See the relevant commit.
Imagine this history: after merge: after rebase: So, the merge does not rewrite your commits. They will stay the same. A rebase _will_ rewrite them. The advantage is that the history looks nicer. The disadvantage is that you usually tested more while developing, so that some obscure feature in, say, "G", could work less nicely together with the changes of, say, "B", than you hope for. In other words, G was tested thoroughly, G' was not. As always, it is a trade-off.
Don't think of 'rm' as the inverse of 'add'. That would only confuse you. When git add is used to add changes made to a file already tracked by git, the inverse of 'git add <file>' is 'git reset HEAD -- <file>'. In the case of adding a new file, a natural inverse of 'add' is 'un-add', and that operation is called 'rm --cached', because we use that to name the option to invoke an "index-only" variant of a command when the command can operate on index and working tree file (e.g. "diff --cached", "apply --cached"). A life of a file that does _not_ make into a commit goes like this: This is 'create', not 'add'. git is not involved in this step. This is 'add'; place an existing file in the index. When you do not want it in the index, you 'un-add' it. This removes the entry from the index, without touching the working tree file. If you do not want that file at all (as opposed to, "I am making a series of partial commits, and the addition of this path does not belong to the first commit of the series, so I am unstaging"), this is followed by Again, git is not involved in this step. People sometimes want to have steps 3 and 4 combined, and it meshes well with the users' expectation when they see the word "rm". Think of "git rm" without "--cached" as a shorthand to do 3 and 4 in one go to meet that expectation. Obviously, we cannot usefully combine steps 1 and 2. We could have "git add --create a-new-file" launch an editor to create a new file, but that would not be very useful in practice. The fact that steps 3 and 4 can be naturally combined, but steps 1 and 2 cannot be, makes "add" and "rm" not inverse of each other. Re: git-rm isn't the inverse action of git-add message by Junio C Hamano. git unadd by Alex Chaffee
Support for this exists in Git versions 1.5 or later. See gitattributes(5).
Not recommended. Keyword expansion causes all sorts of strange problems and isn't really useful anyway, especially within the context of an SCM. Outside git you may perform keyword expansion using a script. The Linux kernel export script does this to set the EXTRA_VERSION variable in the Makefile. See gitattributes(5) if you really want to do this. If your translation is not reversible (eg SCCS keyword expansion) this may be problematic. (Hint: The supplied $Id$-expansion puts the 40-character hexadecimal blob object name into the id; you can figure out which commits include this blob by using a script like this.) See here for a discussion, and here on how GIT may help anyway.
Yes. Not just "keyword expansion" and/or "CRLF conversion", the current version of git allows you to specify filters to munge contents immediately before checking things in. See gitattributes(5) man pages for details.
No. Filenames are treated as byte sequences.
A git repository can store a flag to register the encoding supposedly used for comments (including author names). File content is not converted unless you are inclined to shoot yourself in the foot and use the filtering mechanism described above.
No. Git has a specific notion of tracked "content", which is basically just the file data. It is thus not directly suitable for tracking directories where additional filesystem information is significant, such as "/etc" or home directories. See ContentLimitations for more details.
The push operation is always about propagating the repository history and updating the refs, and never touches the working tree files. In particular, if you push to update the branch that is checked out in a remote repository the files in the work tree will not be updated. This is a precautionary design decision. The remote repository's work tree may have local changes, and there is no way for you, who are pushing into the remote repository, to resolve conflicts between the changes you are pushing and the ones in the work tree. However, you can easily make a post-update hook to update the working copy of the checked out branch. The reason for not making this a default example hook is that they only notify the person doing the pushing if there was a problem. The latest draft post-update hook for this is at https://utsl.gen.nz/git/post-update, which deals with almost all cases, apart from where there is already a conflicted merge on the remote side (as git-stash cannot currently stash this). It also fails to work in instances where it could, such as none of the files are actually conflicting. A quick rule of thumb is to never push into a repository that has a work tree attached to it, until you know what you are doing. If you are sure what you are doing, you can do a "git reset --hard" on the side you pushed to. Note that this WILL lose ALL changes you made on that side, resetting the working tree to the newest revision you pushed. See this article about bare repositories for details. See also the entry (How would I use "git push" to sync out of a firewalled host?) in this FAQ for the proper way to work with push with a repository with a work tree.
There is a bit of a chicken and egg problem involved. The build procedure wants to have an already installed git to figure out the "full" version number. If you are bootstrapping, make clean and rebuild after you install git once would give you a git binary that knows what version it is. GIT-VERSION-GEN script show current (used) git version, git --version shows git version used at the time git was build.
git reset --hard doesn't remove the files which are in the current version of .gitignore. "git reset" won't delete files it doesn't track (particularly when it has been _told_ to ignore them). If the version you switched to has an earlier (different) version of the .gitignore file then the files which were not deleted might be not ignored in the reset version, and will for example show in the git status output. See Linus Torvalds answer or Sean Estabrooks answer at git mailing list. If you are using cygwin or OSX, you might have be having issues with case sensitivity. See some discussion here.
If you try to push a branch, you might get this error message: This means that your branch is not a strict superset of the remote side. That is, the remote side has commits that your side does not have. If you would push, the other side would lose changes. The most likely reason for this is that you need to pull from the remote first. You can see what changes the remote side has by fetching first and then checking the log. For example, will list all the changes the remote side has that your side doesn't. If you want a graphical representation, use gitk --left-right master...origin/master. The arrows to the left are changes you want to push, the arrows to the right are changes on the remote side. If you have rebased your branch and try to push that, see the next question. If you think you know what you are doing, you can also try: This will force the update. If you don't have permission, then sometimes this will work: ie, delete the branch remotely first (this is often permitted), then re-push the "new" (or perhaps rewound) branch. Be warned that if you rewind branches, others might get into problem when pulling. There is the chance that they will merge in the branch that they fetched with the new one that you've published, effectively keeping the changes that you are trying to get rid of. However, it will only be their copies that have the bad revisions. For this reason, rewinding branches is considered mildly antisocial. Nonetheless, it is often appropriate.
After you have rebased one of your local branches, you are trying to push your changes to a remote repository. But git push fails with this error message: This is not a bug, but a safety check: "git push" will not update a remote branch if the remote branch is not a parent of the commit you're trying to push. This check prevents you from overwriting a remote branch to which other people have already commited new changes after you fetched it the last time. Their changes would be lost without the check. And it prevents you from overwriting a remote branch with an unrelated local branch. When you rebase, you are not continuing the history of the branch from where you currently are. Instead, you are rewriting the history starting from the base you chose for rebasing. So, after rebasing, the remote branch and your new local HEAD are both child commits of that base, but the remote branch is no longer a parent of your new local HEAD. And pushing this new history to the remote branch means replacing a history that other people might already have downloaded. If you are really sure that you want to push the new reference to the remote repository you can say git push -f. But use this with care and only if you know what you are doing.
Most other version control systems will do a full-tree commit, using the content of files at commit time, by default. Git does it differently. By default, git commits the content of the index, and only this. git commit -a gives roughly the equivalent of what other systems do. Indeed, there are many concrete reasons why git's way to manage the index is good (and leads to unique features of git): You can select files to commit with a fine granularity, telling git what you want to do little by little (git add file to add the full content of the file to the index, git add -i or git gui to add the content hunk-by-hunk, or even use the hunk splitting feature of git add -i). You can perform several small steps for one commit, checking what you did with git diff, and validating each small step with git add or git add -u. Typically, you can apply a broken patch, updating the index, with git apply --index, and then fix the patch. git diff --cached will show you your fixes, while git diff HEAD will show you the combined diff. This allows excellent management of merge conflicts: git diff --base, git diff --ours, git diff --theirs. This allows git commit --amend to amend only the log message if the index hasn't been modified in the meantime. So, while using git commit -a is perfectly fine with the simple cycle "edit/review/commit", making it the default would make other workflows less natural. Indeed, according to Linus, the real reason is more philosophical: git is a content tracker, and a file name has no meaning unless associated to its content. Therefore, the only sane behavior for git add filename is to add the content of the file as well as its name to the index. See also (mailing list posts): mailing list post: [FAQ?] Rationale for git's way to manage the index mailing list post: [PATCH 0/2] Making "git commit" to mean "git commit -a"
If you push via SSH to the repository, you have to enable the post-update hook (chmod a+x hooks/post-update). If you "push" with rsync, you have to make sure to execute "git update-server-info" _before_ pushing. HTTP is a "dumb" transport, which needs some help. This help is provided in the form of the file info/refs, which contains the current refs (names + commit names of the tips).
Modification time on files is a feature that affects build tools. Most build tools compare the timestamp of the source(s) with the timestamp of the derived file(s). If the source is newer, then a rebuild takes place, otherwise nothing happens. This speeds up the build process a lot. Now consider what would happen if you check out another branch, and modification times were preserved. We assume you already have a fully-built project. If a source file on that other branch has a timestamp that is older than that of the corresponding derived file, the derived file will not be built even if it is different, because the build system only compares modification times. At best, you'll get some kind of weird secondary error; but most likely everything will look fine at first, but you will not get the same result as you would have with a clean build. That situation is unhealthy since you really do not know what code you are executing and the source of the problem is hard to find. You will end up always having to make a clean build when switching branches to make sure you are using the correct source. (Git bisect is another git procedure that checks out old and new revisions where you need a reliable rebuild.) Git sets the current time as the timestamp on every file it modifies, but only those. The other files are left untouched, which means build tools will be able to depend on modification time and rebuild properly. If build rules change, that can cause a failure anyway, but that is a far less common problem than accidentally not rebuilding.
Usually, you are not interested in the whole log, but only some bits at the beginning. It would not be useful for "git log" to simply let the output whiz by, leaving you looking at the uninteresting parts at the end. And if it did it the other way round, showing you the interesting bits last, it would waste a lot of time showing information that you are not interested in at all. So the only thing that makes sense is to look at the log in a pager. It also helps searching for keywords. Note that "--help" just spawns "man", so it is not Git's fault there. But you can use git help -w xxx to use a browser instead of "man" if the HTML documentation is installed. See the git help documentation for more information about this. If you do not like the pager default, you can set core.pager = cat with git config or tell your shell about GIT_PAGER=cat.
Set core.pager = less -FXRS with git config to fix this. The most likely culprit is the LESS environment variable. By default, git passes the options -FXRS to less. The -R option tells less to interpret color escape sequences. If LESS is set, however, only those options are used by less.
git diff and other git operations is optimized so it does not even look at files whose status (size, modification time etc) on disk and in git's index are different. This makes git diff extremely fast for small changes. If the file has been touched somehow, git diff has to look at the content of and compare it which is a much slower operation even when there is in fact no change. git diff lists the files as a reminder that it is not used optimally. Running git status will not only show status, but will also update the index with status for unchanged files disk making subsequent operations, not only diff, much faster. A typical case that causes many files to be listed by diff is running mass editing commands like perl -pi -e '...'.
This is usually caused by color.diff being set to true in your config. git log outputs log entries in colors when color.diff = true. And gitk can only parse plain output. It is recommended (as of 1.5.3) that color.diff be kept off. Use git log --color if you need colored output. This problem should be fixed since version 1.5.4.
This appears to be an issue with your Cygwin configuration. Make sure your CYGWIN environment variable doesn't contain 'tty'.
When running git clone and friends on a partition mounted with sshfs the following error can be triggered: To solve this you need 1) remount your sshfs mounted partition with the -o workaround=rename option, e.g.: and 2) use at least the 1.6.0.2 version of git.
The reason may be that some commits have been developed starting from a version before the "good" commit, and then merged after the "good" commit. See https://thread.gmane.org/gmane.comp.version-control.git/99967/focus=99977 for more explanations from Linus.
You are on a detached HEAD and might lose commits. See https://sitaramc.github.com/concepts/detached-head.html for an excellent discussion of the topic.
The behavior of git log -Ssearchstring is not to compute the diff for each commit and to search for searchstring in it, but to show the commits where the number of occurences of searchstring have changed (which is much faster than grepping the diff). If you want to see all the commits for which searchstring appear in the diff, you can get close to the behavior you expect with a bit of scripting like:
This is not really a git question. However, you can edit your ~/.ssh/config file in order to tell ssh what key to use. More information about this is in the ssh config manpage. The short version is that you can specify a custom Host with its own IdentityFile, like this: Then, you can set up git to use "GitServer" as the hostname. It will look up the entry and use the specified key and host.
If you want to keep a file, but not have it in the next revision, do this:
When a repository is cloned, the clone gets a remote tracking branch for each of the original repository's branch heads, but only a single local branch head is created, usually this will be "master". You can get a list of all remote tracking branches with git branch -r. These remote tracking branches represent the branch heads of the remote repository as of the time you last fetched from the remote. You can use them almost like local branch heads, for example with git log origin/maint, but there's an important exception: git checkout. Trying to checkout a remote tracking branch will leave you with a detached HEAD. So if you want to work on some of these branches, you should create a local branch head for your work and check that out: This will create and checkout a branch head called "maint" that starts at the same commit that the remote tracking branch "origin/maint" currently references.
You can use git --bare init --shared=group (or git --bare init --shared=all for unprivileged gitweb) to initialize a shared repository. All users belonging to your group now have permissions to push their changes to the repository. It's O.K. that refs aren't group writable, it's enough that the directory is. See Git's cvs-migration doc, "Emulating the CVS Development Model" section for details.
Just call git commit with -v flag:
When you work on two machines, sometimes your firewall would let you make a TCP connection only in one direction but not in the other direction. Suppose you start a project on machine A (mothership), and clone from there to a machine B (satellite). You work on B and would want to propagate the change back to your repository on machine A. Even if you wanted to, you cannot run git fetch on machine A to fetch from B, as B is firewalled and does not allow incoming connections. What should you do in such a case? Pushing 'master' branch on B to 'master' branch on A, however, is not what you would want to do. Push is a reverse of fetch in the sense that it propagates the objects and update the branch tips, but does not touch the working tree in the target repository, and you will be utterly confused when you go back to machine A after you update 'master' that way. You can realize that a push is a mirror operation of a fetch and take advantage of it. If B were not firewalled, you would instead run fetch on A from B. And such a fetch is arranged to fetch 'master' from B and store that in 'refs/remotes/B/master' in A. So the simple solution to work around such a firewalled setup is to push 'master' from B into 'refs/remotes/B/master' of A, like this: When you go back to machineA to work further, it is as if you did a git fetch from machineB, like this: When you are ready to integrate the changes you did on machineB into the master branch on machineA, you can: This is no different from the case where you actually pulled from B on A. You can set up your .git/config file to largely automate the above git push, so that you can just say: See also https://thread.gmane.org/gmane.comp.version-control.git/42506/focus=42685
So you cloned that shiny repository and now would like to get the working tree to the state as of some tag? Use git tag -l to list all available tags, then just do a git checkout TAGNAME. If you want to build some work on it, use git checkout -b newbranch TAGNAME instead. If you want to return to your latest revision later, do git checkout ORIGINALBRANCH (usually it is master, you can list them with git branch).
Do and then follow it up with where the '-l' means that it will only put local objects in the pack-file (strictly speaking, it will put any loose objects from the alternate tree too, so you'll have a fully packed archive, but it won't duplicate objects that are already packed in the alternate tree).
There doesn't seem to be a built-in way to do this, but you can do it manually by copying over the unique remote objects and then removing the alternate repository pointer:
You can put shell-style globs (e.g. *.o) in either .git/info/exclude or .gitignore. .git/info/exclude is local to your repository only, and not shared by others who might fetch from your repository. .gitignore is more commonly used, as it can be checked into the repository and thereby automatically shared with all users of the project. git-ls-files(1) man page, section "Exclude Patterns" for details.
Sometimes it is necessary to put some local changes aside, and come back to them later (typically, when one hits an easily-fixable bug in the middle of non-trivial work, and wants to fix the bug before anything else). With recent versions of git, you can use "git stash" to save temporary modifications and come back to a "clean" tree, and then "git stash apply" to re-apply it. Alternatively: One can use a temporary branch, to merge later: where tempBranch is the unique (original) throwaway branch name. Another solution is to save changes in a patch, to apply later: (warning: git reset --hard removes changes to the working tree!)
What to do when you renamed a bunch of files, the merge is having a hard time autoresolving, and you have a couple of conflicts? Suppose the project originally had util/endian.h, and during the course of your development you moved it to src/util/endian.h. Your friend kept working on util/endian.h and it is time to merge the two branches. Sometimes recursive merge strategy (the default) detects this situation, and merge the changes your friend made to util/endian.h to src/util/endian.h without problems (you may still have to resolve the conflict in the contents of the file). But when git thinks you removed util/endian.h and created an unrelated src/util/endian.h file, you will see merge conflicts "your side removed, other side modified" on util/endian.h. First, check which files have conflicts to resolve using git ls-files --unmerged. Then you can see the blob object names for each merge stage; stage1 is from the common ancestor and stage3 is from your friend's branch. When this type of conflict happens, you don't have stage2 for src/util/endian.h, because that path is "only your side created, other side did nothing" case, and (incorrectly) cleanly resolved: Then to do merge between the versions for the "undetected rename" file, extract two blobs (whose sha1 you have from git-ls-files(1) or git-status(1) output) to temporary files, and run "merge" command by hand, e.g. (that is merge yours, original and his). Of course instead of merge from RCS you can use your favorite 3-way file merge program, e.g. Ediff3 from Emacs (see also MergingWithEmacs at Mercurial wiki), vimdiff/gvimdiff, Meld, xxdiff or KDiff3. In newer versions of Git you could use ":<stage>:<filename>" instead of SHA1 to extract files to temporary files (:1:util/endian.h and :3:util/endian.h, respectively); check RevisionSpecification and references therein. Once you come up with the desired state in your file (src/util/endian.h in our example), then you have to inform Git that file was renamed, i.e. say "git update-index --remove util/endian.h" in our example (removing the file from working directory as well, if it exist there) and then "git update-index src/util/endian.h" (you should have it already in the index, so you do not have to say --add).
If you messed up a file, or removed it accidentally, and want to revert file change to version at current commit, you can use: If you want to revert to version in index (i.e. the last version you ran git add on), use
Use command "git show" with a colon and filename: The <commit> can be commit id, branch name, tag, relative pointer like HEAD~2 etc. If you don't give any path or file (i.e. just <commit>:), git will display the file listing of repository's root directory. Examples:
With command "git diff" you can refer to a commit and file pair: As usual, commits can be commit ids, branch names, tags or relative references like HEAD~2. For example:
As Linus said (on gmane): "Generally, the best way to fix things is (I've written this up at somewhat more length before, but I'm too lazy to find it): And remember: git does _not_ make backups pointless. It hopefully makes backups *easy* (since cloning and pulling is easy), but the basic need for backups does not go away!" In another thread (on gmane) Linus explained how to find and fix a corrupt object: "First off, move the corrupt object away, and *save* it. The most common cause of corruption so far has been memory corruption, but even so, there are people who would be interested in seeing the corruption - but it's basically impossible to judge the corruption until we can also see the original object, so right now the corrupt object is useless, but it's very interesting for the future, in the hope that you can re-create a non-corrupt version. So: This is the right thing to do, although it's usually best to save it under it's full SHA1 name (you just dropped the "4b" from the result ;). Let's see what that tells us: Ok, I removed the "dangling commit" messages, because they are just messages about the fact that you probably have rebased etc, so they're not at all interesting. But what remains is still very useful. In particular, we now know which tree points to it! Now you can do which will show something like and you should now have a line that looks like in the output. This already tells you a *lot* it tells you what file the corrupt blob came from! Now, it doesn't tell you quite enough, though: it doesn't tell what *version* of the file didn't get correctly written! You might be really lucky, and it may be the version that you already have checked out in your working tree, in which case fixing this problem is really simple, just do again, and if it outputs the missing SHA1 (4b945..) you're now all done! But that's the really lucky case, so let's assume that it was some older version that was broken. How do you tell which version it was? The easiest way to do it is to do and that will show you the whole log for that file (please realize that the tree you had may not be the top-level tree, so you need to figure out which subdirectory it was in on your own), and because you're asking for raw output, you'll now get something like and this actually tells you what the *previous* and *subsequent* versions of that file were! So now you can look at those ("oldsha" and "newsha" respectively), and hopefully you have done commits often, and can re-create the missing my-magic-file version by looking at those older and newer versions! If you can do that, you can now recreate the missing object with and your repository is good again! (Btw, you could have ignored the fsck, and started with doing a and just looked for the sha of the missing object (4b9458b..) in that whole thing. It's up to you - git does *have* a lot of information, it is just missing one particular blob version. Trying to recreate trees and especially commits is *much* harder. So you were lucky that it's a blob. It's quite possible that you can recreate the thing."
Look for "Repository Administration" in the everyday git document. To setup a git server over http, see the relevant document. As well, it's worth mentioning gitosis is an excellent tool for setting up secure git servers.
See the Git tutorial.
At the moment, git is not able to use a (dumb) sftp protocol for pushing. There is a work around, though: Use sshfs. But make sure that you execute 'git update-server-info' in the pushed repository! Alternatively, you can use whatever means to mirror your .git/ directory to the server (rsync, scp -r, ...). But make sure that 'git update-server-info' was run in that repository _before_ mirroring!
If you just want to checkout the latest source code of a project which may have a very large repo, you can use
In general, git is not a viable solution for the the case of a large repository with relatively small individual checkouts. However, if developers do not intend to clone, fetch, push into or push from their repositories, then use shallow clones
or (to get also the commit message):
Note: It is recommended you backup your repository before using git filter-branch. First, remove the backup references filter-branch created in refs/original: Then clean your reflogs: And finally, repack and drop all the old unreachable objects:
Initialize bare repo: Initialize "fetch"-repo: Update "fetch" repo: Update the "bare" repo by pushing to it: To clone the mirror repository use To enable usage of git svn in the clone use
git rebase -i allows you to conveniently edit any previous commits, except for the root commit. The following commands show you how to do this manually.
Currently, you cannot. There are plans for narrow and sparse clone support. In the meantime, you can use the subdirectory-filter of git filter-branch to extract a subdirectory. You can also merge changes back using the subtree merge strategy. Or you can use submodules. It is possible, however, to download subdirectories or even individual files if the server enables the upload-archive service. The following example retrieves the source code for the main git executable of version 1.6.0. Use git ls-remote to list available versions.
After making sure that there are no uncommitted changes, etc.: The problem with the above process is that it doesn't take into account future internal changes of Git. A safer method is to let Git handle all the internal settings for you by doing something like this.
Save the following script to git-find-large in a directory listed in $PATH. The command git find-large will then list 10 paths corresponding to the largest blobs in your repository. Note that only one path is listed per blob, even if the blob has copies or different names in history.
Make sure your Full Name is not empty in chsh or the 5th field of your user line in /etc/passwd isn't empty. You can also set the GIT_AUTHOR_NAME environment variable. If your @myhost is empty make sure your hostname is correctly set. Use git var -l to make git display user identity variables. See git-var(1)
Using git checkout <branch> or git checkout -b <branch> it just says: You have changes to files in your working directory that will be overwritten, removed or otherwise lost if the checkout and change to the new branch were to proceed. To fix this you may either check your changes in, create a patch of your changes and revert your files, or use the -m flag like this:
The "pu" branch often won't fast forward because some commits have been completely deleted in it since the last time you pulled. If you want to track it, add a plus (+) sign to the proper line in your .git/config file, like this: Which tells git to deal with the problem for you by simply skip the fast forward check (overwriting your old ref with the new one). Or you can just delete that line completely if you don't want to track the pu branch at all. It is conceivable that in future versions of git we might want to be able to mark some branches "this is expected to be rewound" explicitly and make the clone operation to take notice, to give you the plus sign automatically.
If you see the following errors: It likely means you have some extraneous characters, info message or something upon logging into ssh in command mode. To test this, do: You should only see testing commands returned. If there are any other characters, you should examine your dot shell rc file to find any echo or other commands that may produce output.
If you see the following errors: The most likely cause of this error is that you have incorrectly specified the path in the git url. See the git-push(1) man page for more info on valid git urls.
TO DO: Explain first of those messages Second of those error messages is described in git-checkout(1) man page, in the "EXAMPLES" section. It means that you have local modifications to 'frotz', which would be lost on checkout. You can give '-m' option to git checkout, which would try three-way merge. Sometimes the solution is to commit.
Basically the problem is that 'git-receive-pack' is not in the default $PATH on the remote end. You can see the problem using: Whereas you probably installed git to your $HOME or something like that. The workarounds include; Install git to /usr/bin Making sure you have the correct path set up in .bashrc (not only .bash_profile) Specify --receive-pack=PATH/TO/git-receive-pack at push time Set remote.<name>.receivepack using git config (see git-config(1))
Solution : URL-escape the '@' sign in your username, i.e. replace it with %40, like git clone https://user%40mail.com@gitserver.com/path/. Explanation : Git delegates the URL handling to curl, which doesn't allow '@' signs in usernames because RFC 3986 doesn't allow it. See this bug report for example.
See the InterfacesFrontendsAndTools page ("Interaction with other Revision Control Systems" section), for a good reference on how to interact with other revision control systems. Note that you can add/import old history from other revision control system later, and join the histories using Graft Points.
To import from archives (one archive file per version), to make Git know which files changed between versions despite the fact that time stamps on everything changed (i.e. --atime-preserve option of tar didn't work), use between versions, so the index thinks things are newer. It won't touch the "really changed" files.
Yes, use git-cvsimport(1), which needs CVSps (CVSps patches), or use parsecvs, which parses directly ,v files. cvs2svn version 2.1 or later has a git output mode in which it creates dump files that can be read by git fast-import. Lastly, there is also FromCVS toGit, which is a speedy solution with incremental import and branch support, but it currently does not support normal tags. See the CVS migration doc for more examples.
Yes, use git-svn(1). Check also git-svnconvert (in Ruby) in InterfacesFrontendsAndTools. There is also an idea to use svnadmin dump "dumpfile" format as an input for Subversion to Git repository conversion, (similary to what parsecvs does for CVS repositories). Merge tracking information added to svn repositories by svk, svnmerge, or version 1.5 or later of subversion itself, is not properly converted.
Yes, use git-archimport(1), or bzr-fast-export from exporters subdirectory of the bzr-fastimport project.
Yes, there is a number of importers, including one in contrib/ directory of Git source distribution. Search Git mailing list archives for others.
Yes, use for example Rocco Rutte's hg-fast-export (from fast-export.git on repo.or.cz). You can also use hg-git mercurial plugin (https://hg-git.github.com/) that adds to the Mercurial repository ability to push to and pull from a Git server.
Maybe, check if Tailor (homepage) can do it. Take a look at InterfacesFrontendsAndTools page ("Interaction with other Revision Control Systems" section)
GIT FAQ by Thomas Riboulet (defunct). GitCommunity, mainly Git mailing list. Git (software) article at Wikipedia. Why the 'git' name?
What's the difference between fetch and pull?
What can I use to set up a public repository?
Can I add empty directories?
Why does git not "track" renames?
Why is "git log <filename>" slow?
Why is it wrong to export the environment variable CDPATH?
How come gitweb suddenly disappeared from the project list at kernel.org/git?
What is the difference between a merge and a rebase?
- A - B - C - D - remote HEAD
\
E - F - G - local HEAD
- A - B - C - D - remote HEAD
\ \
E - F - G - local HEAD - new local HEAD
- A - B - C - D - remote HEAD - E' - F' - G' - local HEAD'
Why is "git rm" not the inverse of "git add"?
Features
Does git convert between CRLF and LF for different platforms?
Does git have keyword expansion?
Does git allow arbitrary conversion of contents?
Does git convert encodings of file names?
Does git convert encodings of comments and committer names or file content?
Does git track all file data and metadata?
Unexpected behavior
Why won't I see changes in the remote repo after "git push"?
Why is git --version not reporting the "full" version number?
Why is "git reset --hard" not removing some files?
Why is my push rejected with a non-fast forward error?
! [rejected] master -> master (non-fast forward)
error: failed to push some refs to 'git@github.com:pieter/gitx.git'
git fetch origin
git log master..origin/master
git push origin +branchname
git push origin :branchname
git push origin +branchname
Why won't "git push" work after I rebased a branch?
error: remote 'refs/heads/master' is not a strict subset of local ref 'refs/heads/master'. maybe you are not up-to-date and need to pull first?
Why is "git commit -a" not the default?
My HTTP repository has updates, which git clone misses. What happened?
Why isn't Git preserving modification time on files?
Why does git use a pager for commands like diff/log and --help?
Why does diff/log not show color, even though I enabled it?
Why does git diff sometimes list a file that has no changes?
What does the gitk error message "Can't parse git log output:" mean?
Why does gitk on Cygwin display "git 1316 tty_list::allocate: No tty allocated"?
Why does git clone, git pull, etc. fail when run on a partition mounted with sshfs (FUSE)?
$ git clone foo
Cannot commit config file!
Cannot commit config file!
Cannot commit config file!
Initialized empty Git repository in foo/.git/
294698 blocks
Cannot commit config file!
fatal: Not a valid object name HEAD
sshfs -o workaround=rename login@machine:foo bar
Why does "git bisect" make me test versions outside the "good-bad" range?
Why am I "not on any branch"?
"git log -S" does not show all commits
git log -p -z | perl -ln0e 'print if /[+-].*searchedstring/'
How do I ...
How do I specify what ssh key git should use?
Host GitServer
Hostname=git.example.org
IdentityFile=~/.ssh/my_cool_key_rsa
How do I untrack a file?
git rm --cached <filename>
How do I access other branches in a repository?
Vienna:git pieter$ git branch -r
origin/HEAD
origin/html
origin/maint
origin/man
origin/master
Vienna:git pieter$ git checkout -b maint origin/maint
Branch maint set up to track remote branch refs/remotes/origin/maint.
Switched to a new branch "maint"
Vienna:git pieter$
How do I share a git public repository and use it in a CVS way?
How can I add a diff of the commit into the commit message window?
git commit -v
How would I use "git push" to sync out of a firewalled host?
machineB$ git push machineA:repo.git master:refs/remotes/B/master
machineA$ git fetch machineB:repo.git master:refs/remotes/B/master
machineA$ git merge B/master ;# shorthand for refs/remotes/B/master
machineB$ git push
How do I check out the tree at a particular tag?
How to share objects between existing repositories?
echo "/source/git/project/.git/objects/" > .git/objects/info/alternates
git repack -a -d -l
How to stop sharing objects between repositories?
(cd /path/to/alternate/repo.git/objects && tar cp .) | (cd .git/objects && tar xvpk)
# some objects will already exist and be skipped, leading to an error on exit, which is fine
rm .git/objects/info/alternates
# or if there's more than one and you're only removing one, edit the alternates file and remove only that pointer
How do I tell git to ignore files?
How do I save some local modifications?
$ git checkout -b tempBranch
$ git commit -a -m "to test"
$ git diff --binary HEAD > tempPatch.diff
$ git reset --hard
How to manually resolve conflicts when Git failed to detect rename?
$ git ls-files --unmerged --abbrev
...
100755 33cd1f76... 1 util/endian.h
100755 7f531bb7... 3 util/endian.h
$ git cat-file blob 33cd1f76 >endian.h-1
$ git cat-file blob 7f531bb7 >endian.h-3
$ merge src/util/endian.h endian.h-1 endian.h-3
How to revert file to version from current commit?
git checkout HEAD -- <file>
git checkout -- <file>
How to view an old revision of a file or directory?
git show <commit>:path/file
git show v1.4.3:git.c
git show f5f75c652b9c2347522159a87297820103e593e4:git.c
git show HEAD~2:git.c
git show master~4:
git show master~4:doc/
git show master~4:doc/ChangeLog
How do I make a diff between two arbitrary files in different revisions?
git diff <commit1>:path/file <commit2>:otherpath/otherfile
git diff 06de3718c389fd5038697151c49519f6e9f2dbe0:ChangeLog HEAD~2:ChangeLog.old
How to fix a broken repository?
$ mv .git/objects/4b/9458b3786228369c63936db65827de3cc06200 ../
$ git fsck --full
> broken link from tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
> to blob 4b9458b3786228369c63936db65827de3cc06200
> missing blob 4b9458b3786228369c63936db65827de3cc06200
git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
100644 blob 8d14531846b95bfa3564b58ccfb7913a034323b8 .gitignore
100644 blob ebf9bf84da0aab5ed944264a5db2a65fe3a3e883 .mailmap
100644 blob ca442d313d86dc67e0a2e5d584b465bd382cbf5c COPYING
100644 blob ee909f2cc49e54f0799a4739d24c4cb9151ae453 CREDITS
040000 tree 0f5f709c17ad89e72bdbbef6ea221c69807009f6 Documentation
100644 blob 1570d248ad9237e4fa6e4d079336b9da62d9ba32 Kbuild
100644 blob 1c7c229a092665b11cd46a25dbd40feeb31661d9 MAINTAINERS
...
10064 blob 4b9458b3786228369c63936db65827de3cc06200 my-magic-file
git hash-object -w my-magic-file
git log --raw --all --full-history -- subdirectory/my-magic-file
commit abc
Author:
Date:
...
:100644 100644 4b9458b... newsha... M somedirectory/my-magic-file
commit xyz
Author:
Date:
...
:100644 100644 oldsha... 4b9458b... M somedirectory/my-magic-file
git hash-object -w <recreated-file>
git log --raw --all
How to set up a git server?
How to create the first project?
How do I publish my repo via SFTP?
How do I do a quick clone without history revisions?
git clone --depth 1 your_repo_url
How do I use git for large projects, where the repository is large, say approaching 1 TB, but a checkout is only a few hundred MB? Will every developer need 1 TB of local disk space?
git clone --depth 1 <url>
How do I obtain a list of files which have changed in a given commit?
git diff --name-only <commit>^!
git show --name-only <commit>
How do I remove all the old objects after using filter-branch?
git for-each-ref --format='%(refname)' refs/original | \
while read ref
do
git update-ref -d "$ref"
done
git reflog expire --expire=0 --all
git repack -ad
git prune # For objects that repack -ad might have left around
How do I mirror a SVN repository to git?
mkdir project.git
cd project.git
git init --bare
cd ..
git svn clone -s svn://.../project
git remote add bare /path/to/project.git
git config --unset remote.bare.fetch
git config remote.bare.push 'refs/remotes/*:refs/heads/*'
git push bare
cd project
git svn fetch
cd project
git push bare
git clone git://$your_repo
git svn init -s --prefix=origin/ svn://.../project
How do I edit the root commit?
# tag the old root
git tag root `git rev-list HEAD | tail -1`
git checkout -b new-root root
# edit...
git commit --amend
# check out the previous branch
git checkout @{-1}
# replace old root with amended version
git rebase --onto new-root root
# cleanup
git branch -d new-root
git tag -d root
How do I clone a subdirectory?
git archive --remote=git://repo.or.cz/git.git v1.6.0 git.c > git.c.tar
How do I make existing non-bare repository bare?
$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo
* ssh to remote server
* git clone --bare -l <path_to_repos> <new_dir>
* renamed old repository directory
* renamed new repository dir to what old repository used to be.
How do I find large files?
#!/bin/sh
#
# From https://mid.gmane.org/20090710114316.GA6880@atjola.homenet
#
usage() {
echo "usage: `basename $0` [<limit>]"
exit 1
}
limit=10
if test $# -gt 1
then
usage
elif test $# -eq 1
then
limit=$1
fi
git rev-list --all --objects |
sed -n $(git rev-list --objects --all |
cut -f1 -d' ' | git cat-file --batch-check | grep blob |
sort -n -k3 | tail -n$limit | while read hash type size;
do
echo -n "-e s/$hash/$size/p ";
done) |
sort -n -k1
Error diagnostic
Git commit is dying telling me "fatal: empty ident <user@myhost> not allowed", what's wrong?
Why won't git let me change to a different branch?
fatal: Entry 'foo.c' not uptodate. Cannot merge.
$ git checkout -m -b my-branch
refs/heads/pu: does not fast forward to branch 'pu'
[remote "origin"]
fetch = +refs/heads/pu:refs/remotes/origin/pu
protocol error: bad line length character
fatal: protocol error: bad line length character
error: failed to push to 'git.example.com:/Repo/Project.git'
fatal: The remote end hung up unexpectedly
ssh user@git.example.com echo testing commands
"unable to chdir or not a git archive" while pushing
fatal: 'git.exaple.com/wrong-path': unable to chdir or not a git archive
fatal: The remote end hung up unexpectedly
error: failed to push to 'git.exaple.com/wrong-path'
"needs update" and "not uptodate"
foo: needs update
fatal: Entry 'frotz' not uptodate. Cannot merge.
"git-receive-pack: command not found" on push/fetch/pull
$ ssh servername 'echo $PATH'
/usr/bin:/bin
$
My username contains a '@', I can't clone through HTTP/HTTPS
$ git clone https://user@mail.com@gitserver.com/path/
[...]
error: Couldn't resolve host 'user@mail.com' while accessing https://user@mail.com@gitserver.com/path/info/refs
Importing from other revision control systems
Can I import from tar files (archives)?
$ git update-index --refresh
Can I import from CVS?
Can I import from svn?
Can I import from arch/baz/tla?
Can I import from Perforce?
Can I import from Mercurial?
Can I import from other SCMs?
References
GitFaq (last edited 2009-11-01 12:31:36 by 80)