This is not a tutorial for beginner. If you know commit
, push
, pull
, and want to master more Git features, it’s for you. You can read it in any order, or use it as a handbook, or refer to it when you encounter problems.
git config --global user.name "Dongyuan Liu"
git config --global user.email "[email protected]"
git commit --author "Xhacker <[email protected]>"
or
GIT_COMMITTER_NAME="Xhacker" GIT_COMMITTER_EMAIL="[email protected]" git commit --author "Xhacker <[email protected]>"
What’s the difference? In fact, there are two kinds of information about the author, committer
and author
. The first command uses Xhacker <[email protected]>
as the author
of the commit. The second one sets both committer
and author
.
About the difference, it’s mentioned in Pro Git Chapter 2.3:
You may be wondering what the difference is between author and committer. The author is the person who originally wrote the work, whereas the committer is the person who last applied the work. So, if you send in a patch to a project and one of the core members applies the patch, both of you get credit – you as the author, and the core member as the committer. We’ll cover this distinction a bit more in Distributed Git.
Sometimes you are working on both personal work and company work. You may want to set different committer information for them, it’s easy:
git config user.name "Dongyuan Liu"
git config user.email "[email protected]"
As you can see, when you git config
you are modifying the config for the current repo. If you add --global
, you can modify the global config.
Commit messages describe what you have done in commits. They should be short and distinct. Please use simple present tense.
Good examples:
Fix table view cell text overflow
Fix a memory leak
Bad examples:
fixed some bugs
update file
Meanwhile, if you are using GitHub, you can close issues via commit messages (official documentation), like:
[Close #40] Send Dribbble shots from XPC service in batches
Say you realized there’s a mistake in the commit you’ve just made. Instead of creating a new commit, you may want to append the simple fix to the last commit. Just use --amend
:
git commit --amend
Keep in mind that amending will not change the time information in the commit. If you want to update the time in the commit, use
git commit --amend --reset-author
Beware that amend
actually modified the last commit. If you had already pushed the last commit, please don’t use amend
.
If you insisted on amending a pushed commit, please make sure that you are the only one using the branch (or it’s a disaster for other contributors), then use git push --force
after amending.
git commit -p
Then, Git will prompt for each hunk of the modification, ask if you want to stage:
diff --git a/Source/Player.swift b/Source/Player.swift
index af1cb7f..6ee0213 100644
--- a/Source/Player.swift
+++ b/Source/Player.swift
@@ -323,9 +323,7 @@ public class Player: UIViewController {
}
private func setupPlayerItem(playerItem: AVPlayerItem?) {
- let item = playerItem
-
- if item == nil {
+ if self.playerItem != nil {
self.playerItem?.removeObserver(self, forKeyPath: PlayerEmptyBufferKey, context: &PlayerItemObserverContext)
self.playerItem?.removeObserver(self, forKeyPath: PlayerKeepUp, context: &PlayerItemObserverContext)
self.playerItem?.removeObserver(self, forKeyPath: PlayerStatusKey, context: &PlayerItemObserverContext)
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?
Use y
/n
to choose whether or not to commit this hunk, ?
to show help for other operations.
Git has the concept of staging area. It’s like a temporary area. When you run git commit
, only modifications in the staging area will be committed. If you are making a huge change, staging area could help you to commit a part of the change. You can stage a file via git add <filename>
; You can also stage part of a file via git add -p
(similar to git commit -p
).
git status
shows the status of uncommitted files. It shows files in stating area (to be committed) at the top; modified but not stated at the middle; untracked files at the bottom:
On branch fix-kvo-crash
Your branch is behind 'origin/fix-kvo-crash' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: Source/InboardHelper.swift
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: Source/InboardHelperDelegate.swift
Untracked files:
(use "git add <file>..." to include in what will be committed)
SyncManager.swift
git diff
shows the unstated modifications. git diff --staged
shows the modifications in staging area.
To check the modifications in a commit, use git show
:
# Show the modifications in the last commit
git show
# Show the modifications in the third commit before last
git show HEAD~3
# Show the modifications in commit `deadbeef`
git show deadbeef
HEAD
is a pointer to the last commit, HEAD~3
is the third commit before the last.
In Git, hash is a SHA-1 checksum for the content of the commit. It usually represented by a 40-digit hex number, e.g. a502950cd563f2ed210d6610bf5d82f72827ea19
. However, as long as there’s no conflicts, you can use a shorter prefix to represent a commit. For example, git show a50295
, git checkout a50295
.
There are two ways to create a new branch:
# Create a new branch branch
git branch <branchname>
# Create and switch to the new branch (commonly used)
git checkout -b <branchname>
git branch -d <branchname>
git checkout <branchname>
# Switch to the last branch
git checkout -
Similar to cd -
, isn’t it?
git checkout -- <filepath>
git reset --hard
git revert <commit SHA>
You may ask what’s the difference between revert
and reset
. The essence of revert
is to create a new commit which is the exact opposite of the reverted commit. For example, A
commit added three lines in main.c
, reverting A
would create a new commit to remove the three lines. If we are very sure that a previous commit caused a bug, the best way is to revert it.
After running git revert
, git will prompt you to write a commit message. You’d better briefly describe the reason for the revert.
Revert "Use DDT to kill insects" because it has so many side effects
This reverts commit 4281ac1c58e21194b80a327af93d47c5fefb786f.
But reset
will modify the history. It usually used by local commits that haven’t been pushed.
git reset --soft
git fetch
git rebase origin/master
You can close GitHub issues via commit messages. You have to use close
, fix
, or other special words in the commit message, see Closing issues via commit messages for details.
For example, issue 42 can be closed by either of the following two commit messages:
[Fix #42] Fix table view cell text overflow
Fix table view cell text overflow, close #42
git bisect
The debate between CLI and GUI never ends. In my opinion, the most efficient way to use Git is the cooperation between a good GUI client and CLI. Before pushing the commit, carefully examine its content is a good habit. In a GUI client, you can see the modifications clearly. Another typical use case of GUI is to commit a part of a file. In this case, GUI is way more intuitive than git add -p
.
- GitHub Desktop (free): Supports Mac and Windows. Highly recommended. It doesn’t have a lot of features, but it’s well-organized.
- SourceTree (free): Supports Mac and Windows. Compared to GitHub Desktop, it’s more feature-rich. The UI is a bit messy in my point of view.
- Tower (paid): The client I’m currently using. It’s expensive, but it’s feature-rich and very easy to use.