# 试着输入git,看看系统有没有安装Git:
$ git
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git
# 安装命令
sudo apt-get install git
'''
如果是其他Linux版本,可以直接通过源码安装。
先从Git官网下载源码,然后解压,依次输入:./config,make,sudo make install 这几个命令安装就好了。
'''
两种安装Git的方法:
在 Windows 上使用 Git,可以从 Git 官网直接下载安装程序,然后按默认选项安装即可。
安装完成后,在开始菜单里找到 “Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明 Git 安装成功!
安装完成后,还需要最后一步设置,在命令行输入:
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
注意:
git config 命令的 –global 参数,用了这个参数,表示你这台机器上所有的 Git 仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和 Email 地址。
Git 支持 SSH 协议,本地 Git 仓库和 GitHub 仓库之间的传输是通过 SSH 加密的,所以需要设置:
创建 SSH Key
在用户主目录下,看看有没有 .ssh 目录,如果有,再看看这个目录下有没有 id_rsa 和 id_rsa.pub 这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开 Shell( Windows 下打开 Git Bash ),创建 SSH Key:
$ ssh-keygen -t rsa -C "[email protected]"
如果一切顺利的话,可以在用户主目录里找到 .ssh 目录,里面有 id_rsa 和 id_rsa.pub 两个文件,这两个就是 SSH Key 的秘钥对,id_rsa 是私钥,不能泄露出去,id_rsa.pub 是公钥,可以放心地告诉任何人。
GitHub 添加 SSH Key
登陆 GitHub,打开 “Account settings”,“SSH Keys” 页面
然后,点 “Add SSH Key”,填上任意 Title,在 Key 文本框里粘贴 id_rsa.pub 文件的内容
点 “Add Key”,你就应该看到已经添加的 Key
准备工作:
git clone 克隆远程仓库到本地库
$ git clone git@github.com:michaelliao/gitskills.git
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Receiving objects: 100% (3/3), done.
git add 把文件修改添加到暂存区
'''
git add 文件名: 提交指定的文件到暂存区
git add . : 提交本地所有修改的文件到暂存区 (一般开发都使用)
'''
$ git add readme.txt
$ git commit -m "branch test"
[dev b17d20e] branch test
1 file changed, 1 insertion(+)
git commit 提交更改,实际上就是把暂存区的所有内容提交到当前分支
$ git commit -m "understand how stage works"
[master e43a48b] understand how stage works
2 files changed, 2 insertions(+)
create mode 100644 LICENSE
git status 查看一下状态
$ git status
On branch master
nothing to commit, working tree clean
git pull origin name 拉取某分支最新的远程代码
注意:本地开发需求推送远端最好先拉取一下远端仓库的最新代码,避免合并冲突。
如何解决冲突请参考:https://www.liaoxuefeng.com/wiki/896043488029600/900004111093344
git push origin name 推送分支
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git 就会把该分支推送到远程库对应的远程分支上:
$ git push origin master
如果要推送其他分支,比如 dev,就改成:
$ git push origin dev
但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
总之,就是在 Git 中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!
创建本地 dev 分支,并且创建完成后切换到 dev 分支:
$ git checkout -b dev
Switched to a new branch 'dev'
git checkout 命令加上 -b 参数表示创建并切换,相当于以下两条命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
git branch 命令查看当前分支:
$ git branch
* dev
master
git branch 命令会列出所有分支,当前分支前面会标一个 ***** 号
git checkout 分支,切换到指定的分支
$ git checkout master
Switched to branch 'master'
git checkout – file 丢弃工作区的修改:
命令 git checkout – readme.txt 意思就是,把 readme.txt 文件在工作区的修改全部撤销,这里有两种情况:
一种是 readme.txt 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是 readme.txt 已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次 git commit 或 git add 时的状态。
# 初始状态
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
'情况1':修改后还没有被放到暂存区
# 修改文件
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
My stupid boss still prefers SVN.
# 查看工作区状态 (暂存区有修改)
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
# 放弃对文件的修改
$ git checkout -- readme.txt
# 查看文件对比初始状态(文件内容复原了)
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
'情况2':已经添加到暂存区后,又作了修改
# 修改文件
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
My stupid boss still prefers SVN.
# 提交到暂存区
$ git add readme.txt
# 查看工作区状态 (暂存区有修改)
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
modified: readme.txt
# 把暂存区的修改回退到工作区 (当我们用 HEAD 时,表示最新的版本)
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
# 查看工作区状态 (暂存区是干净的,工作区有修改)
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: readme.txt
# 放弃对文件的修改
$ git checkout -- readme.txt
# 查看工作区状态 (没有任何提交,工作区是干净的)
$ git status
On branch master
nothing to commit, working tree clean
删除文件
直接删除
$ rm test.txt
git rm & git commit
$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
误删恢复
可以把误删的文件恢复到最新版本:
$ git checkout -- test.txt
git checkout 其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以**“一键还原”**。
分支合并
dev 分支的工作完成,我们就可以切换回 master 分支,把 dev 分支的工作成果合并到 master 分支上
$ git checkout master
Switched to branch 'master'
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
删除分支
$ git branch -d dev
Deleted branch dev (was b17d20e).
switch 用法
切换分支使用 git checkout
实际上,切换分支这个动作,用 switch 更科学。因此,最新版本的 Git 提供了新的 git switch 命令来切换分支:
创建并切换到新的 dev 分支
$ git switch -c dev
直接切换到已有的 master 分支
$ git switch master
使用新的 git switch 命令,比 git checkout 要更容易理解。
git remote -v 查看远程库信息
$ git remote -v
origin git@github.com:michaelliao/learn-git.git (fetch)
origin git@github.com:michaelliao/learn-git.git (push)
关联一个远程库
关联一个远程库时必须给远程库指定一个名字,origin 是默认习惯命名
关联后,使用命令 git push -u origin master 第一次推送 master 分支的所有内容
此后,每次本地提交后,只要有必要,就可以使用命令 git push origin master 推送最新修改
$ git remote add origin git@server-name:path/repo-name.git
删除远程库
$ git remote rm origin
总结:
克隆远程仓库到本地仓:git clone
提交修改到暂存区: git add
提交暂存区的修改到当前分支: git commit -m “修改信息”
查看本地分支状态:git status
将当前分支的提交推送到远程分支: git push origin name
查看提交历史:git log
查看命令历史:git reflog
拉取远程分支最新代码:git pull origin name
查看分支:git branch
创建分支:git branch
切换分支:git checkout
创建+切换分支:git checkout -b
合并某分支到当前分支:git merge
删除分支:git branch -d
查看远程库:git remote -v
关联一个远程库:git remote add origin
删除远程库:git remote rm origin
Git 允许我们在版本的历史之间穿梭,使用命令 git reset --hard commit_id
实际工作中,版本控制系统肯定有某个命令可以告诉我们历史记录,在 Git 中,我们用 git log 命令查看每次都改了什么内容:
$ git log
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:06:15 2018 +0800
append GPL
commit e475afc93c209a690c39c13a46716e8fa000c366
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:03:36 2018 +0800
add distributed
commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 20:59:18 2018 +0800
wrote a readme file
git log 命令显示从最近到最远的提交日志
上述示例我们可以看到3次提交,最近的一次是 append GPL ,上一次是 add distributed ,最早的一次是 wrote a readme file 。
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上 –pretty=oneline 参数:
$ git log --pretty=oneline
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file
友情提示:
你看到的一大串类似 1094adb… 的是 commit id (版本号),和 SVN 不一样,Git 的 commit id 不是 1,2,3…… 递增的数字,而是一个 SHA1 计算出来的一个非常大的数字,用十六进制表示,而且你看到的 commit id 和我的肯定不一样,以你自己的为准。为什么 commit id 需要用这么一大串数字表示呢?因为 Git 是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用 1,2,3…… 作为版本号,那肯定就冲突了。
每提交一个新版本,实际上 Git 就会把它们自动串成一条时间线。如果使用可视化工具查看 Git 历史,就可以更清楚地看到提交历史的时间线
Git 必须知道当前版本是哪个版本,在 Git 中,用 HEAD 表示当前版本,也就是最新的提交 1094adb… ,上一个版本就是 HEAD^ ,上上一个版本就是 HEAD^^ ,当然往上100个版本写100个 ^ 比较容易数不过来,所以写成 HEAD~100。
现在,我们要把当前版本 append GPL 回退到上一个版本 add distributed ,就可以使用 git reset 命令:
$ git reset --hard HEAD^
HEAD is now at e475afc add distributed
指定回到未来的某个版本 (git reset --hard commit_id) :
$ git reset --hard 1094a
HEAD is now at 83b0afe append GPL
版本号没必要写全,前几位就可以了,Git 会自动去找。当然也不能只写前一两位,因为 Git 可能会找到多个版本号,就无法确定是哪一个了。
Git 的版本回退速度非常快,因为 Git 在内部有个指向当前版本的 HEAD 指针,当你回退版本的时候,Git 仅仅是把 HEAD 从指向 append GPL:
┌────┐
│HEAD│
└────┘
│
└──> ○ append GPL
│
○ add distributed
│
○ wrote a readme file
改为指向 add distributed :
┌────┐
│HEAD│
└────┘
│
│ ○ append GPL
│ │
└──> ○ add distributed
│
○ wrote a readme file
然后顺便把工作区的文件更新了。所以你让 HEAD 指向哪个版本号,你就把当前版本定位在哪。
现在,你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的 commit id 怎么办?
在 Git 中,总是有后悔药可以吃的。当你用 $ git reset --hard HEAD^ 回退到 add distributed 版本时,再想恢复到 append GPL ,就必须找到 append GPL 的 commit id。Git 提供了一个命令 git reflog 用来记录你的每一次命令:
$ git reflog
e475afc HEAD@{1}: reset: moving to HEAD^
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL
e475afc HEAD@{3}: commit: add distributed
eaadf4e HEAD@{4}: commit (initial): wrote a readme file
从输出可知, append GPL 的 commit id 是 1094adb ,可以使用命令 git reset --hard 1094adb 指定回到这个版本。
切换到需要打标签的分支上 (默认标签是打在最新提交的 commit 上的) :
$ git branch
* dev
master
$ git checkout master
Switched to branch 'master'
然后,敲命令 git tag
$ git tag v1.0
可以用命令 git tag 查看所有标签:
$ git tag
v1.0
给指定的 commit 打标签
# 查看历史提交
$ git log --pretty=oneline --abbrev-commit
5dc6824 & simple
14096d0 AND simple
b17d20e branch test
# 选择需要的 commit id
$ git tag v0.9 14096d0
# 查看标签
$ git tag
v0.9
v1.0
'''
注意:
标签不是按时间顺序列出,而是按字母排序的
可以用 git show 查看标签信息
'''
$ git show v0.9
commit 14096d049bc3c1593499807e5c8e972b82c8f286 (tag: v0.9)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:56:54 2018 +0800
AND simple
diff --git a/readme.txt b/readme.txt
...
创建带有说明的标签,用 -a 指定标签名,-m 指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 1094adb
用命令 git show
$ git show v0.1
tag v0.1
Tagger: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 22:48:43 2018 +0800
version 0.1 released
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (tag: v0.1)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:06:15 2018 +0800
append GPL
diff --git a/readme.txt b/readme.txt
...
总结:
标签打错可以删除:
$ git tag -d v0.1
Deleted tag 'v0.1' (was f15b0dd)
因为创建的标签都只存储在本地,不会自动推送到远程,所以打错的标签可以在本地安全删除。
如果要推送某个标签到远程,使用命令 git push origin
$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
* [new tag] v1.0 -> v1.0
或一次性推送全部尚未推送到远程的本地标签:
$ git push origin --tags
Total 0 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
* [new tag] v0.9 -> v0.9
如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:
$ git tag -d v0.9
Deleted tag 'v0.9' (was f52c633)
然后从远程删除,删除命令也是 push,格式如下:
$ git push origin :refs/tags/v0.9
To github.com:michaelliao/learngit.git
- [deleted] v0.9
要看看是否真的从远程库删除了标签,可以登陆 GitHub 查看
总结:
参考:https://www.liaoxuefeng.com/wiki/896043488029600