65.9K
CodeProject 正在变化。 阅读更多。
Home

Git 手册

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.25/5 (3投票s)

2014 年 4 月 4 日

CPOL

3分钟阅读

viewsIcon

24678

日常使用的 Git

引言

我不会深入探讨版本控制的历史或其他类似内容。在本文中,我的目标是创建一个快速的 Git 操作指南。顺便说一下,如果你是 Git 新手,我会把它描述为“一个带有时间机器的文件系统上的宇宙飞船”。你可以在任何空间定格时间,然后回到那些定格的时刻,并从那个时间点重新开始。我觉得我快要陷入平行宇宙和相关的悖论了。尽管如此,我还是想活在 Git 里。

背景

在使用 Git 时,需要记住两个重要要点。

文件的三种状态

  • 已修改(在 工作目录 中修改文件)
  • 已暂存(准备提交到 暂存区
  • 已提交(定格在 仓库 中)

上面加粗的词是 Git 中的常用术语。工作目录是 Git 跟踪的目录。当你将在工作目录中创建一个文件时,Git 会将其标记为未跟踪。你的未跟踪和已修改的文件,除非你显式地将它们添加到暂存区,否则永远不会进入仓库。当你暂存了所有工作后,就可以将它们提交到仓库,这意味着你会在那个时间点定格文件系统。

HEAD 在哪里?

HEAD 是 Git 系统中的一个特殊指针。它可以被认为是指向你即将提交的位置。当你告诉 Git 提交时,HEAD 指示了将当前空间定格的时间点。在 Git 中工作时,请始终了解你的 HEAD 的位置。

开始之前的最后一点。记住,当你犹豫不决时,请查阅帮助。

$git help <git_command>

Content

  1. 使用文件
  2. 使用目录
  3. 提交
  4. 分支
  5. 远程仓库
  6. Stashing(贮藏)

使用 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).

Rebasing(从不同分支追加最新工作) || 返回内容

### 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

这本书包含了您可能需要的一切

https://git-scm.cn/book

© . All rights reserved.