I had been using Git for about 18 months and thought I had a pretty good handle on it, but when we had Scott Chacon from GitHub come to LVS (a gaming/gaming software vendor/developer) to do a special training session, I learned a ton on the first day. Since some people always feel good about using Git, I wanted to share some of the Git gems I got from the community, so that it might help those people find the answer directly without wasting a lot of research time. Basic Tips 1. The first step after installation After installing Git, the first thing you should do is to configure your name and email address, as this information is required for every commit:
2. Git is pointer-based Everything stored in git is contained in a single file. When you commit, git creates a file containing the commit message and relevant data (name, email, date/time, last commit, etc.), and links it to a tree file. The tree file contains a list of objects or other trees. The object or binary large data object (BLOB) is the real content of the commit (a file, if you will, although the file name is not stored in the object, but it is stored in the tree). All of these files are stored with the SHA-1 hash of the object as the file name. Branches and tags are just files that contain (basically) a SHA-1 hash pointing to a commit. Using these references gives you a huge increase in flexibility and speed; creating a new branch is as simple as creating a file with the branch name and a SHA-1 hash pointing to the commit you're branching from. Of course, you'll never do this when using the Git command-line tool (or a GUI), but it's that simple. You may have heard of references to HEAD. It's just a file that contains a SHA-1 reference to your current commit. If you're resolving a merge conflict, take a look at HEAD and you'll see that it has nothing to do with a specific branch or point on a branch, just where you are right now. All branch pointers are stored in .git/refs/heads, HEAD is in .git/HEAD, and tags are in .git/refs/tags - feel free to look around. 3. Two Parents - Of course! When viewing a merge commit's message in the log file, you'll see two parents (compared to a normal commit). The first parent is the branch you were on, and the second parent is the branch you merged into. 4. Merge Conflicts By now I'm sure you have a merge conflict that needs to be resolved. Usually this is done by editing the file, removing the <<<<, ====, >>>> markers from the file, and then saving the code you want to keep. Sometimes it's advisable to review the code before making any changes, for example, before you take action on two conflicting branches. Here's another command:
If the files are binary, file comparison is not so easy... What you usually do is try each version of the binary and decide which one to use (or manually copy parts of it in a binary editor). Pull a copy of the files from a specific branch (if you are merging master with branch 132):
Another way is to view this file from git - you can view it as a different file name, then copy the correct file (when you're sure which one it is) to the normal file name:
Update: Thanks to Carl for the heads-up in an earlier blog comment, you can actually use "git checkout --ours flash/foo.fla" and "git checkout --theirs flash/foo.fla" to check out a specific revision without having to remember which branch you were merging into. I personally prefer to be more explicit, but take your pick... After resolving the merge conflicts (like I did above), remember to add this file to the index. Servers, branches, and tags 5. Remote Server One of the most powerful features of Git is the ability to have more than one remote server (another fact to the fact that you can always run a local repository). You don't always need write access, you can read from multiple servers (for merging) and write to another. Adding a remote server is simple:
If you want to view information about the remote server, you can do this:
You can view the differences between your local branch and the remote branch:
You can also view changes to HEAD that is not on a remote branch:
6. Tags There are two types of tags in Git - a lightweight tag and an annotated tag. Remember from the second tip that Git is pointer-based, the difference between the two is simple. A lightweight tag is nothing more than a named pointer to a commit. You can change it to point to another commit. An annotated tag is a named pointer to a tag object, which has its own message and history. The tag object's message can be cryptographically signed with GPG if desired. Creating both types of tags is easy (just a difference in command line options):
7. Create a branch Creating branches in Git is very easy (lightning fast, since it only requires creating a file of less than 100 bytes). The general syntax for creating a new branch and switching to it is:
Of course, if you know you want to switch to it right away, you can do it with a single command:
If you want to rename a local branch, it's also easy (the long command is used to show the specific execution process):
Update: Or you can (as Brian Palmer points out in the blog post comments) do it all in one go by just using "git branch" with the -m option:
#p# 8. Merge branches At some point in the future, you will want to merge your changes. There are two ways to do this:
The difference between merge and rebase is that merge tries to resolve changes and create a new commit that is amalgamated, while rebase tries to reproduce the changes you made since last time on the other branch, on top of the other branch's HAED. However, do not rebase after you have pushed a branch to a remote server - this will cause confusion/problems. If you are unsure which branches still have independent work in progress - so that you know which branches you need to merge and which branches you need to delete, the git branch command has two options to help with this:
9. Remote branches If you have a local branch that you want to make available on the remote server, you can use a push command:
Update: Thanks to Erlend for pointing this out in the comments to the blog post - this is effectively the same as git push origin twitter-experiment , but by using the full syntax you can see that you're actually using different names on both ends (your local name might be add-ssl-support, and the remote name might be issue-1723). If you want to delete a branch on a remote server (note the colon before the branch name):
If you want to show the status of all remote branches, you can view them like this:
This may list some branches that used to exist on the server but no longer exist. If this is the case, you can easily check them out locally and delete them with the following command:
Finally, if you have a remote branch that you want to track locally, the usual approach is:
However, newer versions of Git will automatically set up tracking if you check out using the -b flag:
Saving content in temporary storage, index, and file system 10. Stashing In Git, you can store the current working state in a temporary storage area called a stack and reuse it later. A simple example is as follows:
Many people recommend using git stash apply instead of "pop", however if you do this you will end up with a long list of useless stashes. If you clean it up, "pop" will just remove it from the stash. If you have already used git stash apply, you can remove the last item from the stash with the following command:
Git will automatically create a comment based on the current commit message. If you prefer to use a custom message (because it may not be relevant to the previous commit):
If you want to make use of a specific stash from your list (not necessarily the last one), you can list them and use it like this:
11. Interactive Addition In the Subversion world, you modify files and then commit only the changed files. In the Git world, you have more control over committing certain files or even certain patches. In order to commit certain files or certain parts of files, you must enter interactive mode.
This will put you into a menu-based interactive command mode. You can use the command number sign or the highlighted character (if you have color highlighting turned on) to enter the corresponding mode, and then it's a matter of entering the file number normally (you can use a format like 1 or 1-4 or 2,4,7). If you want to enter patch mode (type 'p' or '5' in interactive mode), you can also enter that mode directly:
As you can see, at the bottom you get a series of options to choose to add only the changed parts of the file, all changes to the file, etc. Use the '?' command to get an explanation of the different options. 12. Store/Retrieve from File System Some projects (such as the Git project itself) store additional files directly in the Git file system without necessarily checking them in. Let's start by storing an arbitrary file in Git:
At this point, the file object is in the database, but if you don't set (something) to point to that file object, it will be garbage collected. The easiest way to do this is to mark it:
Now that we have marked myfile here, when we need to get the file, we can do it like this:
This is useful for programmers who may frequently use utility files (passwords, GPG keys, etc.) without having to check them out to disk every time (especially in a production environment). Logging 13. View logs If you don't use 'git log' to see the recent commit history, you won't be able to use Git successfully for long. However, there are some suggestions on how to use it better. For example, you can view a patch changed in each commit:
Or you can just see an overview of which files have changed:
You can set up a nice alias for showing short commits and a nice branch graph with messages in one line (like gitk, but on the command line):
#p# 14. Retrieve Logs If you want to query the logs for a specific author, you can specify that like this:
Update: Thanks to Johannes's comment, I finally solved some of the confusion. Or if you have a search term that appears in the commit message:
There is a more powerful command called pickaxe, which finds entries for adding or removing a particular content (that is, when it first appeared or was removed). This lets you know when a line was added (but you won't know if the characters in that line are subsequently changed):
What happens if you change a specific file, say lib/foo.rb
For example, if you have a feature/132 branch and a feature/145 branch, and you want to see the commits that are on these branches but not on the master branch (note: ^ stands for not):
You can also use the ActiveSupport style dates to narrow the date range:
It uses OR mode to combine queries by default, but you can easily change it to AND mode (if you have more than one query term)
15. Select the version to view/modify When referencing a revision, you have a number of options, depending on how familiar you are with the feature:
Note that, unlike in the previous section, the caret at the end of the line indicates the parent of the commit - a caret at the beginning indicates that it is not on this branch. 16. Select a range The simplest way is to use it like this:
You can also remove [new], which will use the current HEAD. Time rollback and bug fixes 17. Reset changes If you haven't committed a change yet, you can easily reset it:
It is usually better to use 'unstage' as an alias because it is less obvious.
If you have already committed the file, you can do two things - if it is the last commit, you can modify it like this:
This will roll back the last commit, returning your working copy to the state where the changes were stored in the staging area, and you can edit the commit message and prepare the next commit. If you have more than one commit and just want to roll them back completely, you can reset the branch to go back to an earlier point in time.
If you really want to point a branch to a completely different SHA-1 (perhaps you're pointing the HEAD of one branch to another branch, or one commit further), you can do it in the following way:
There is actually a more convenient way (because it doesn't change your working copy back to the original FOO state and then point to the SHA):
18. Committing to the wrong branch OK, let's assume you're committed to the master branch, but you should have created a topic branch called experimental. To remove those changes, you can create a branch at the current point, revert HEAD, and then check out the new branch:
This is more complicated if you have made changes on a branch on a branch on a branch on a branch etc. Then all you need to do is rebase the changes on that branch onto the other one:
19. Interactive rebasing This is a cool feature that I've seen demonstrated before but didn't really understand at the time, but now it's actually pretty simple. Let's say you've made 3 commits, but you want to reorder or edit them (or merge them):
Then you have your editor open. All you have to do is change the "pick/squash/edit" instructions to how you want to commit, then save/exit. After editing, you can use git rebase --continue to run your instructions one by one. If you choose to edit a file, this will leave you at the state you committed, so you will need to use git commit --amend to edit it. Note: Do not commit work during a REBASE - only add and then use the --continue, --skip or --abort options. 20. Clean up If you have already committed some content to your branch (perhaps you imported it from an old repository in SVN), and you want to remove all commits from your history:
If you've already pushed code to the remote server, but have committed garbage since then, you can do this on your local system before pushing:
#p# Various tips 21. Quotes you have read before If you know you've viewed a SHA-1 before, but you've done some resetting/rewinding work, you can use the reflog command to see the most recently viewed SHA-1:
22. Branch Naming A nice little tip - remember that branch names are not limited to characters like az and 0-9. You can use / and . in the name to disguise the namespace or revision number, for example:
23. Find out who is the culprit It is often used to find who changed a line of code in a file. The simple command is as follows:
Sometimes the changes come from a previous file (if you've merged two files, or you've moved a function), so you can use:
Sometimes it's nice to track changes by clicking forward or backward. There's a built-in GUI program designed for this:
24. Database Maintenance Git does not usually require a lot of maintenance and is mostly self-maintaining. However, you can view database statistics using the following command:
If the number is high, you can choose to garbage collect your duplicates. This won't affect pushes or other users, but it will make your commands run faster and take up less space:
It is also recommended to run consistency checks frequently:
You can also add an --auto parameter to the end of the line (if you run it frequently, or run it daily from crontab on your server) to only fsck the command if statistics indicate that a consistency check is necessary. If the check says "dangling" or "unreachable" everything is fine, this is often the result of reverting HEAD or rebasing. If the check says "missing" or "sha1 mismatch" something is wrong... get professional help! 25. Recovering a lost branch If you deleted a branch experimental using the -D option, you can recreate it:
You can use git reflog to discover a SHA-1 hash if you have visited it recently. Another way is to use git fsck --lost-found. A dangling commit is a lost HEAD (it would only be the HEAD of a deleted branch, since when a HEAD^ is referenced by a HEAD, it is not dangling) |
<<: Don’t miss it if you pass by! Four major impacts of Windows 10 on web design
At the bottom of the spiral channel, there will b...
This article shares with you 30 high-quality case...
In the field of operations , a major difference b...
Some time ago, the Content Marketing Institute (C...
The scenario sounds like science fiction: autonom...
From a unicorn to falling from the altar, from cr...
It is the day to welcome the God of Wealth on the...
As user behavior undergoes tremendous changes in ...
"The first thing about whole grains is that ...
As the Spring Festival approaches, with the optim...
[51CTO.com Quick Translation] The rapid populariz...
Chinese companies are facing an inflection point ...
Where will marketing go in 2018? Consumption and ...
The risk of asteroid impact is a major threat fac...
Editor's note: When running an event , giving...