Git 手册






4.25/5 (3投票s)
日常使用的 Git
引言
我不会深入探讨版本控制的历史或其他类似内容。在本文中,我的目标是创建一个快速的 Git 操作指南。顺便说一下,如果你是 Git 新手,我会把它描述为“一个带有时间机器的文件系统上的宇宙飞船”。你可以在任何空间定格时间,然后回到那些定格的时刻,并从那个时间点重新开始。我觉得我快要陷入平行宇宙和相关的悖论了。尽管如此,我还是想活在 Git 里。
背景
在使用 Git 时,需要记住两个重要要点。
文件的三种状态
- 已修改(在 工作目录 中修改文件)
- 已暂存(准备提交到 暂存区)
- 已提交(定格在 仓库 中)
上面加粗的词是 Git 中的常用术语。工作目录是 Git 跟踪的目录。当你将在工作目录中创建一个文件时,Git 会将其标记为未跟踪。你的未跟踪和已修改的文件,除非你显式地将它们添加到暂存区,否则永远不会进入仓库。当你暂存了所有工作后,就可以将它们提交到仓库,这意味着你会在那个时间点定格文件系统。
HEAD 在哪里?
HEAD 是 Git 系统中的一个特殊指针。它可以被认为是指向你即将提交的位置。当你告诉 Git 提交时,HEAD 指示了将当前空间定格的时间点。在 Git 中工作时,请始终了解你的 HEAD 的位置。
开始之前的最后一点。记住,当你犹豫不决时,请查阅帮助。
$git help <git_command>
Content
使用 Git
使用文件
在当前目录中启动新仓库 || 返回内容
$ git init Initialized empty Git repository in /cygdrive/d/projects/test/.git/ ### 'status' command shows the current state of your work ### and mostly tells you how to proceed. ### in this case, there is nothing to commit and it tells you that you ### can use 'add' command to track a file. $ git status # On branch master # # Initial commit # nothing to commit (create/copy files and use "git add" to track)
暂存文件(准备提交) || 返回内容
### create a file $ touch 1.c ### see what happens $ git status # On branch master # # Initial commit # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # 1.c nothing added to commit but untracked files present (use "git add" to track) ### we have an untracked file, and we can track it by using 'add' command as ### it says $ git add 1.c ### check status $ git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: 1.c # ### 1.c is now staged (can be committed into the repo). ### if you like, you can take it out of the staging area (which makes it untracked) ### by using 'rm --cached' command as it says.
### commit the staged files with a commit note $ git commit -m "first file added" [master (root-commit) 55b349c] first file added 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 1.c ### see the status $ git status # On branch master nothing to commit (working directory clean)
### 'rm' command does two things: ### 1- removes file from working directory, ### 2- stages this change (makes ready to commit) $ git rm 1.c rm '1.c' $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # deleted: 1.c #
### reset HEAD for this file (unstage this change) $ git reset HEAD 1.c Unstaged changes after reset: D 1.c ### now this change is not staged. $ git status # On branch master # Changes not staged for commit: # (use "git add/rm <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # deleted: 1.c # no changes added to commit (use "git add" and/or "git commit -a") ### call back 1.c from the last commit point to the working directory $ git checkout 1.c $ git status # On branch master nothing to commit (working directory clean)
将文件添加到忽略列表 || 返回内容
### create a file $ touch 2.out ### create '.gitignore' special file ### this file shows which patterns will not be tracked by Git. $ echo .gitignore > .gitignore $ echo 2.out >> .gitignore ### git doesn't see '2.out' anymore $ git status # On branch master nothing to commit (working directory clean)
### use 'mv' command $ git mv 1.c 2.c $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: 1.c -> 2.c #
将更改添加到上一次提交(如果你忘记了一些小事) || 返回内容
### create some files $ touch 2.c 3.c ### add them to the staging area $ git add . $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: 2.c # new file: 3.c # ### commit changes $ git commit -m "new files added" [master 830d12c] new files added 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 2.c create mode 100644 3.c ### oops, forgotten comments in 1.c $ echo aa > 1.c ### 1.c is modified $ git status # On branch master # 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: 1.c # no changes added to commit (use "git add" and/or "git commit -a") ### add last changes to the staging area $ git add . ### 'commit --amend' to append those changes to the last commit $ git commit --amend [master d1941e8] new files added 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 2.c create mode 100644 3.c
使用目录
### create a directory and a file in it $ mkdir dir1 $ touch dir1/11.c ### see status $ git status # On branch master # Untracked files: # (use "git add <file>..." to include in what will be committed) # # dir1/ nothing added to commit but untracked files present (use "git add" to track) ### add changes to the staging area $ git add . $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: dir1/11.c # ### commit changes $ git commit -m "dir1 added" [master bc39a14] dir1 added 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 dir1/11.c
$ git rm -r dir1 rm 'dir1/11.c' $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # deleted: dir1/11.c #
$ git reset HEAD dir1 Unstaged changes after reset: D dir1/11.c $ git checkout dir1 $ git status # On branch master nothing to commit (working directory clean)
$ git mv dir1 dir2 $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: dir1/11.c -> dir2/11.c #
将目录添加到忽略列表 || 返回内容
$ mkdir dir2 $ touch dir2/21.c ### caution: adding 'dir2/' makes a recursive description. ### all 'dir2/'s will be ignored in every directory. $ echo "dir2/" >> .gitignore $ git status # On branch master nothing to commit (working directory clean)
提交
### every commit is pointed by its checksum calculated over some statistics of that commit. ### checksum has 40 hex chars, output of SHA-1 algorithm $ git log commit d1941e8a7f76067c4ea300d10ca6ad18fa8f6264 Author: ozanoner Date: Mon Mar 31 21:02:59 2014 +0300 new files added commit 55b349ca5142282124bdef0ebb8cf9b46e1bb96f Author: ozanoner Date: Mon Mar 31 20:39:40 2014 +0300 first file added
### list commits one-line, reverse ordered by its date $ git log --pretty=oneline d1941e8a7f76067c4ea300d10ca6ad18fa8f6264 new files added 55b349ca5142282124bdef0ebb8cf9b46e1bb96f first file added ### tag a commit $ git tag v0.1 55b349ca5142282124bdef0ebb8cf9b46e1bb96f ### tag latest commit $ git tag v0.2 ### list tags $ git tag v0.1 v0.2 ### list tags and commit messages $ git tag -n v0.1 first file added v0.2 new files added
### shows commit (checksum, author, date, message, changes) tagged as 'v0.2' $ git show v0.2 commit d1941e8a7f76067c4ea300d10ca6ad18fa8f6264 Author: ozanoner Date: Mon Mar 31 21:02:59 2014 +0300 new files added diff --git a/1.c b/1.c index e69de29..e61ef7b 100644 --- a/1.c +++ b/1.c @@ -0,0 +1 @@ +aa diff --git a/2.c b/2.c new file mode 100644 index 0000000..e69de29 diff --git a/3.c b/3.c new file mode 100644 index 0000000..e69de29
### delete tag v0.2 (nothing with commit) $ git tag -d v0.2 Deleted tag 'v0.2' (was d1941e8) ### list tags with commit messages $ git tag -n v0.1 first file added
分支
### create a new branch named 'test_branch' from the current branch $ git branch test_branch ### make it active branch ### HEAD is on 'test_branch' now $ git checkout test_branch Switched to branch 'test_branch' ### edit 1.c version in 'test_branch' $ echo bb >> 1.c ### add changes to the staging area and commit them ('commit -a') $ git commit -am '1.c edited in new branch' ### show branches $ git branch -v master f694fb8 first commit * test_branch 44e91ae 1.c edited in new branch
合并到主分支 ('master') 并删除临时分支 ('test_branch') || 返回内容
### make 'master' active branch (ie. HEAD moved to 'test_branch') $ git checkout master Switched to branch 'master' ### merge 'test_branch' onto 'master' $ git merge test_branch Updating f694fb8..44e91ae Fast-forward 1.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) ### check logs to see what happened $ git log commit 44e91aea6ee69b874e1cbb2e73390fb5e0eb68bb Author: ozanoner Date: Wed Apr 2 15:34:28 2014 +0300 1.c edited in new branch commit f694fb8f1c30c9564be9a8bf32392dc84b4559a8 Author: ozanoner Date: Wed Apr 2 15:32:14 2014 +0300 first commit $ git status # On branch master nothing to commit (working directory clean) ### we are done with 'test_branch'. delete it $ git branch -d test_branch Deleted branch test_branch (was 44e91ae).
### create 'new_dev' and move HEAD to it. $ git checkout -b new_dev Switched to a new branch 'new_dev' ### edit 1.c in 'new_dev' $ echo dd >> 1.c ### stage and commit $ git commit -am 'modified in new_dev' [new_dev 385f6a9] modified in new_dev 1 files changed, 1 insertions(+), 0 deletions(-) ### move HEAD to 'master' branch $ git checkout master Switched to branch 'master' ### compare 'new_dev' and the current branch ('master') $ git diff new_dev diff --git a/1.c b/1.c index 955bebf..3b7dd8b 100644 --- a/1.c +++ b/1.c @@ -1,4 +1,3 @@ aa bb cc -dd ### compare file versions on different branches $ git diff master:1.c new_dev:1.c diff --git a/master:1.c b/new_dev:1.c index 3b7dd8b..955bebf 100644 --- a/master:1.c +++ b/new_dev:1.c @@ -1,3 +1,4 @@ aa bb cc +dd
### edit 2.c in 'master' $ echo aa > 2.c ### and stage changes $ git add . ### this change is included in comparison since it is in the staging area. $ git diff new_dev diff --git a/1.c b/1.c index 955bebf..3b7dd8b 100644 --- a/1.c +++ b/1.c @@ -1,4 +1,3 @@ aa bb cc -dd diff --git a/2.c b/2.c new file mode 100644 index 0000000..e61ef7b --- /dev/null +++ b/2.c @@ -0,0 +1 @@ +aa ### change to 2.c is not visible by the latest commit in branch 'master' $ git diff new_dev master diff --git a/1.c b/1.c index 955bebf..3b7dd8b 100644 --- a/1.c +++ b/1.c @@ -1,4 +1,3 @@ aa bb cc -dd ### merge 'master' and 'new_dev' $ git merge new_dev Updating 97d650c..385f6a9 Fast-forward 1.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) ### no difference between 'master' and 'new_dev' $ git diff master new_dev ### delete 'new_dev' branch $ git branch -d new_dev Deleted branch new_dev (was 385f6a9).
### create and switch to 'testing' branch $ git checkout -b testing Switched to a new branch 'testing' ### edit 1.c in 'testing' $ echo ccc >> 1.c ### stage and commit $ git commit -am '1.c corrected' [testing 0c8e0a2] 1.c corrected 1 files changed, 1 insertions(+), 0 deletions(-) ### append it to 'master' $ git rebase master Current branch testing is up to date. ### switch to 'master' $ git checkout master Switched to branch 'master' ### this 'merge' command just re-aligns 'master' $ git merge testing Updating 1d5b72e..0c8e0a2 Fast-forward 1.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) $ cat 1.c aa bb ccc ### delete 'testing' branch $ git branch -d testing Deleted branch testing (was 0c8e0a2)
远程仓库
### clone remote repository in the current directory. ### that means remote repo is duplicated in local directory as 'master' branch. ### note that another branch created as 'origin/master' in local repo ### representing remote branch $ git clone https://github.com/ozanoner/test . Cloning into '.'... remote: Counting objects: 5, done. remote: Compressing objects: 100% (2/2), done. remote: Total 5 (delta 0), reused 3 (delta 0) Unpacking objects: 100% (5/5), done. ### see log for this new repo $ git log commit 44a94d529c9be2920e62400ee570ebdb23c101fd Author: ozanoner Date: Tue Apr 1 15:15:01 2014 +0300 Delete README.txt commit 4cf94f8556d45e258cc127b891c1a6add1f1617c Author: ozanoner Date: Tue Apr 1 15:13:44 2014 +0300 first commit
从远程仓库获取(刷新 origin/master || 返回内容
### list remote repos $ git remote -v origin https://github.com/ozanoner/test (fetch) origin https://github.com/ozanoner/test (push) ### fetch from remote repo into local representation (origin/master) $ git fetch origin remote: Counting objects: 4, done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From https://github.com/ozanoner/test 44a94d5..1ea2bab master -> origin/master ### no change in 'master' yet $ git log commit 44a94d529c9be2920e62400ee570ebdb23c101fd Author: ozanoner Date: Tue Apr 1 15:15:01 2014 +0300 Delete README.txt commit 4cf94f8556d45e258cc127b891c1a6add1f1617c Author: ozanoner Date: Tue Apr 1 15:13:44 2014 +0300 first commit ### merge 'master' and 'origin/master' $ git merge origin/master Updating 44a94d5..1ea2bab Fast-forward README.md | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 README.md ### changes in remote repo is now merged into 'master' ### README.md file is added. $ git log commit 1ea2babd342e1432626d6536afbcce320005b643 Author: ozanoner Date: Thu Apr 3 10:39:09 2014 +0300 Create README.md commit 44a94d529c9be2920e62400ee570ebdb23c101fd Author: ozanoner Date: Tue Apr 1 15:15:01 2014 +0300 Delete README.txt commit 4cf94f8556d45e258cc127b891c1a6add1f1617c Author: ozanoner Date: Tue Apr 1 15:13:44 2014 +0300 first commit
从远程仓库拉取(获取到 'origin/master' 并合并到 'master') || 返回内容
### pull command (fetch&merge) $ git pull origin remote: Counting objects: 4, done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From https://github.com/ozanoner/test 1ea2bab..b456638 master -> origin/master Updating 1ea2bab..b456638 Fast-forward 1.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 1.c ### see last 2 logs $ git log -2 commit b456638c54a61595c1f112cdb13ac5574aaba58c Author: ozanoner Date: Thu Apr 3 10:43:30 2014 +0300 Create 1.c commit 1ea2babd342e1432626d6536afbcce320005b643 Author: ozanoner Date: Thu Apr 3 10:39:09 2014 +0300 Create README.md
### create a file and commit changes $ touch 2.c $ git commit -am '2.c added' [master 50b88d7] 2.c added 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 2.c ### push changes to remote 'origin' ### as from local 'master' branch to remote 'master' branch $ git push origin master:master Username for 'https://github.com': Password for 'https://ozanoner@github.com': Counting objects: 4, done. Delta compression using up to 8 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 289 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To https://github.com/ozanoner/test b456638..50b88d7 master -> master
### create and switch to branch 'testing' $ git checkout -b testing Switched to a new branch 'testing' ### create a file and commit changes $ echo aa > 2.c $ git commit -am 'testing 2.c' [testing 7be7133] testing 2.c 1 files changed, 1 insertions(+), 0 deletions(-) ### push changes to remote 'origin' ### from local branch 'testing' to remote branch 'testing' $ git push origin testing:testing Username for 'https://github.com': Password for 'https://ozanoner@github.com': Counting objects: 3, done. Delta compression using up to 8 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 219 bytes, done. Total 2 (delta 1), reused 0 (delta 0) To https://github.com/ozanoner/test 50b88d7..7be7133 testing -> testing
查找与远程仓库的差异 || 返回内容
### first fetch into local 'origin/master' branch $ git fetch origin remote: Counting objects: 1, done. remote: Total 1 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (1/1), done. From https://github.com/ozanoner/test 50b88d7..b26e2af master -> origin/master ### then see the difference $ git diff origin diff --git a/2.c b/2.c index e61ef7b..e69de29 100644 --- a/2.c +++ b/2.c @@ -1 +0,0 @@ -aa
Stashing(临时保存状态)
### create a branch (dont switch yet) $ git branch testing ### modify file in the current branch $ echo cc >> 1.c $ git status # On branch master # 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: 1.c # no changes added to commit (use "git add" and/or "git commit -a") ### want to switch branch 'testing' but need to save current state without commit ### solution is stashing $ git stash Saved working directory and index state WIP on master: e01a00f Update 1.c HEAD is now at e01a00f Update 1.c ### move HEAD to 'testing' branch $ git checkout testing Switched to branch 'testing' ### done with 'testing', switch to 'master' $ git checkout master Switched to branch 'master' ### oops, status tells us no change $ git status # On branch master nothing to commit (working directory clean) ### forgotten to apply temporary versions, therefore apply stash $ git stash apply # On branch master # 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: 1.c # no changes added to commit (use "git add" and/or "git commit -a") ### done with that stash, drop it $ git stash drop Dropped refs/stash@{0} (e62a20cd9ff4053dfcd64e26d038955f2274de54)
|| 返回内容
参考文献
无需多言,但
https://www.google.com.tr/#q=git+reference+book
这本书包含了您可能需要的一切