---恢复内容开始---
Git工作流程
1.Git 仓库之基本操作
创建目录 $ mkdir first_git_file $ cd first_git_file/
$ vim first_git_file.txt
'''添加内容''' first time using git, excited!
初始化创建 $ git init """提示:Initialized empty Git repository in /Users/alex/git_trainning/.git/"""
Git 使用 git init 命令来初始化一个 Git 仓库
#用命令git add告诉Git,把文件添加到仓库, git add . 把所有的文件添加到仓库
git add first_git_file.txt
提交 (使用 git add 命令将想要快照的内容写入缓存区)
$ gi
t commit -m
"commit my first git file"
查看状态
git status git status (以查看在你上次提交之后是否有修改)
日志 git diff first_git_file.txt (查看具体修改内容) git log (查看最近到最远的日志) git log --pretty=oneline (查看看现在版本库的状态) git checkout 文件名 (通过git status 获取 modified:XXX) 把当前代码从暂存区回滚到工作区 git reflog 查看所有的操作记录
撤销修改 git checkout -- file可以丢弃工作区的修改:
代码回滚可以通过日志获取到 版本号 回滚到该版本
gitreset --hard HEAD 回滚到上次 gitreset --hard 323423ds 回滚到指定的版本
删除 1 $ rm test.txt ----> git add . --->> git commit -m 'del' 2 $ git rm test.txt ----> git commit -m 'del' git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
2.Git 远程仓库
https://github.com 创建账号 密码
1.ssh 无密码传输
由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:
第1步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了, 可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key: $ ssh-keygen -t rsa -C "xxxxx@example.com" 户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥
第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面: 然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:
2.创建远程仓库
第一步:
第二步:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!创建成功!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3.远程GitHub 仓库命令:
git add .
git commit -m
"add home page"
git remote add origin git@github.com:github名字/仓库名.git #添加远程仓库 git push -u origin master #推到远程 提示信息:
The authenticity of host
'github.com (192.30.253.113)'
can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to
continue
connecting (
yes
/no
)?
yes
#第一次推会出现,写yes
Warning: Permanently added
'github.com,192.30.253.113'
(RSA) to the list of known hosts.
Counting objects: 20,
done
.
Delta compression using up to 8 threads.
Compressing objects: 100% (14
/14
),
done
.
Writing objects: 100% (20
/20
), 1.76 KiB | 0 bytes
/s
,
done
.
Total 20 (delta 4), reused 0 (delta 0)
remote: Resolving deltas: 100% (4
/4
),
done
.
To git@github.com:triaquae
/oldboy_website
.git
* [new branch] master -> master
Branch master
set
up to track remote branch master from origin.
第二次以后 提交
git push origin master #推到远程
git clone克隆一个本地库
在本地找一个存放远程仓库的目录,然后在本地命令行用git clone 命令来克隆这个远程库
$ git clone git@github.com:triaquae/gitskills.git 提示信息:Cloning into 'gitskills'...Warning: Permanently added the RSA host key for IP address '192.30.253.112' to the list of known hosts.remote: Counting objects: 3, done.remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0Receiving objects: 100% (3/3), done.Checking connectivity... done. $ cd gitskills/ #进入刚clone下来的目录$ lsREADME.md
4.分支管理
1 创建与合并分支 git checkout -b dev 2.切换分支
git checkout master 3.查看分支
git branch 4. 合并分支 git merge dev 重要提示: 每次修改完 必须 add commit
bug分支 软件开发中,bug就像家常便饭一样。有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交:12345678910111213$ git status# On branch dev# Changes to be committed:# (use "git reset HEAD..." to unstage)## new file: hello.py## 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# 并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug,怎么办?幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:123$ git stashSaved working directory and index state WIP on dev: 6224937 add mergeHEAD is now at 6224937 add merge现在,用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支:12345$ git checkout masterSwitched to branch 'master'Your branch is ahead of 'origin/master' by 6 commits.$ git checkout -b issue-101Switched to a new branch 'issue-101'现在修复bug,需要把“Git is free software ...”改为“Git is a free software ...”,然后提交:1234$ git add readme.txt$ git commit -m "fix bug 101"[issue-101 cc17032] fix bug 101 1 file changed, 1 insertion(+), 1 deletion(-)修复完成后,切换到master分支,并完成合并,最后删除issue-101分支:123456789$ git checkout masterSwitched to branch 'master'Your branch is ahead of 'origin/master' by 2 commits.$ git merge --no-ff -m "merged bug fix 101" issue-101Merge made by the 'recursive' strategy. readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)$ git branch -d issue-101Deleted branch issue-101 (was cc17032). 太棒了,原计划两个小时的bug修复只花了5分钟!现在,是时候接着回到dev分支干活了!12345$ git checkout devSwitched to branch 'dev'$ git status# On branch devnothing to commit (working directory clean) 工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看:12$ git stash liststash@{ 0}: WIP on dev: 6224937 add merge工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;另一种方式是用git stash pop,恢复的同时把stash内容也删了:1234567891011121314$ git stash pop# On branch dev# Changes to be committed:# (use "git reset HEAD ..." to unstage)## new file: hello.py## 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#Dropped refs/stash@{ 0} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)再用git stash list查看,就看不到任何stash内容了:1$ git stash list你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:1$ git stash apply stash@{ 0}
5.多人协作
当你从远程仓库克隆时,实际上Git自动把本地的master
分支和远程的master
分支对应起来了,并且,远程仓库的默认名称是origin
。
要查看远程库的信息,用git remote
:
1 2 | $ git remote origin |
或者,用git remote -v
显示更详细的信息:
1 2 3 | $ git remote - v origin git@github.com:triaquae /gitskills .git (fetch) origin git@github.com:triaquae /gitskills .git (push) |
上面显示了可以抓取和推送的origin
的地址。如果没有推送权限,就看不到push的地址。
10.1 推送分支
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
1 | $ git push origin master |
如果要推送其他分支,比如dev
,就改成:
1 | $ git push origin dev |
但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
-
master
分支是主分支,因此要时刻与远程同步; -
dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步; -
bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
-
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!
10.2 抓取分支
多人协作时,大家都会往master
和dev
分支上推送各自的修改。
现在,模拟一个你的小伙伴,可以在另一台电脑(注意要把SSH Key添加到GitHub)或者同一台电脑的另一个目录下克隆:
1 2 3 4 5 6 7 | $ git clone git@github.com:triaquae /gitskills .git Cloning into 'gitskills' ... remote: Counting objects: 16, done . remote: Compressing objects: 100% (7 /7 ), done . remote: Total 16 (delta 0), reused 10 (delta 0), pack-reused 0 Receiving objects: 100% (16 /16 ), done . Checking connectivity... done . |
当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的master
分支。不信可以用git branch
命令看看:
1 2 | $ git branch * master |
现在,你的小伙伴要在dev
分支上开发,就必须创建远程origin
的dev
分支到本地,于是他用这个命令创建本地dev
分支:
1 | $ git checkout -b dev origin /dev |
现在,他就可以在dev
上继续修改,然后,时不时地把dev
分支push
到远程:
1 2 3 4 5 6 7 8 9 10 11 12 13 | $ git add . $ git commit -m "small updates" [dev f1b762e] small updates 2 files changed, 5 insertions(+), 1 deletion(-) Alexs-MacBook-Pro:gitskills alex$ git push origin dev Counting objects: 4, done . Delta compression using up to 8 threads. Compressing objects: 100% (3 /3 ), done . Writing objects: 100% (4 /4 ), 438 bytes | 0 bytes /s , done . Total 4 (delta 0), reused 0 (delta 0) To git@github.com:triaquae /gitskills .git 33ec6b4..f1b762e dev -> dev |
你的小伙伴已经向origin/dev分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $ git add . $ git commit -m "add Dog class" [dev 7e7b1bf] add Dog class 2 files changed, 7 insertions(+) $ git push origin dev To git@github.com:triaquae /gitskills .git ! [rejected] dev -> dev (fetch first) error: failed to push some refs to 'git@github.com:triaquae/gitskills.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g., 'git pull ...' ) before pushing again. #提示你了,先把远程最新的拉下来再提交你的 hint: See the 'Note about fast-forwards' in 'git push --help' for details. |
推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull
把最新的提交从origin/dev
抓下来,然后,在本地合并,解决冲突,再推
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $ git pull remote: Counting objects: 4, done . remote: Compressing objects: 100% (3 /3 ), done . remote: Total 4 (delta 0), reused 4 (delta 0), pack-reused 0 Unpacking objects: 100% (4 /4 ), done . From github.com:triaquae /gitskills 33ec6b4..f1b762e dev -> origin /dev There is no tracking information for the current branch. Please specify which branch you want to merge with. See git-pull(1) for details. git pull <remote> <branch> If you wish to set tracking information for this branch you can do so with: git branch -- set -upstream-to=origin/<branch> dev |
git pull
也失败了,原因是没有指定本地dev
分支与远程origin/dev
分支的链接,根据提示,设置dev
和origin/dev
的链接:
1 2 | $ git branch -- set -upstream-to=origin /dev dev Branch dev set up to track remote branch dev from origin. |
再pull:
1 2 3 4 5 6 | $ git pull Auto-merging hello.py CONFLICT (content): Merge conflict in hello.py Auto-merging branch_test.md CONFLICT (content): Merge conflict in branch_test.md Automatic merge failed; fix conflicts and then commit the result. |
这回git pull
成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $ git add . $ git commit -m "merge & fix hello.py" [dev 93e28e3] merge & fix hello.py $ git push origin dev Counting objects: 8, done . Delta compression using up to 8 threads. Compressing objects: 100% (7 /7 ), done . Writing objects: 100% (8 /8 ), 819 bytes | 0 bytes /s , done . Total 8 (delta 1), reused 0 (delta 0) remote: Resolving deltas: 100% (1 /1 ), done . To git@github.com:triaquae /gitskills .git f1b762e..93e28e3 dev -> dev |
因此,多人协作的工作模式通常是这样:
-
首先,可以试图用
git push origin branch-name
推送自己的修改; -
如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; -
如果合并有冲突,则解决冲突,并在本地提交;
-
没有冲突或者解决掉冲突后,再用
git push origin branch-name
推送就能成功!
如果git pull
提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name
。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
11. github使用
我们一直用GitHub作为免费的远程仓库,如果是个人的开源项目,放到GitHub上是完全没有问题的。其实GitHub还是一个开源协作社区,通过GitHub,既可以让别人参与你的开源项目,也可以参与别人的开源项目。
在GitHub出现以前,开源项目开源容易,但让广大人民群众参与进来比较困难,因为要参与,就要提交代码,而给每个想提交代码的群众都开一个账号那是不现实的,因此,群众也仅限于报个bug,即使能改掉bug,也只能把diff文件用邮件发过去,很不方便。
但是在GitHub上,利用Git极其强大的克隆和分支功能,广大人民群众真正可以第一次自由参与各种开源项目了。
如何参与一个开源项目呢?比如人气极高的bootstrap项目,这是一个非常强大的CSS框架,你可以访问它的项目主页,点“Fork”就在自己的账号下克隆了一个bootstrap仓库,然后,从自己的账号下clone:
1 | git clone git@github.com:michaelliao /bootstrap .git |
一定要从自己的账号下clone仓库,这样你才能推送修改。如果从bootstrap的作者的仓库地址git@github.com:twbs/bootstrap.git
克隆,因为没有权限,你将不能推送修改。
Bootstrap的官方仓库twbs/bootstrap
、你在GitHub上克隆的仓库my/bootstrap
,以及你自己克隆到本地电脑的仓库,他们的关系就像下图显示的那样:
如果你想修复bootstrap的一个bug,或者新增一个功能,立刻就可以开始干活,干完后,往自己的仓库推送。
如果你希望bootstrap的官方库能接受你的修改,你就可以在GitHub上发起一个pull request。当然,对方是否接受你的pull request就不一定了。
如果你没能力修改bootstrap,但又想要试一把pull request,那就Fork一下我的仓库:https://github.com/triaquae/gitskills ,创建一个your-github-id.txt
的文本文件,写点自己学习Git的心得,然后推送一个pull request给我,我会视心情而定是否接受。
小结
-
在GitHub上,可以任意Fork开源仓库;
-
自己拥有Fork后的仓库的读写权限;
-
可以推送pull request给官方仓库来贡献代码。
12. 忽略特殊文件.gitignore
有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,每次git status
都会显示Untracked files ...
,有强迫症的童鞋心里肯定不爽。
好在Git考虑到了大家的感受,这个问题解决起来也很简单,在Git工作区的根目录下创建一个特殊的.gitignore
文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
不需要从头写.gitignore
文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:
忽略文件的原则是:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的
.class
文件; - 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
举个例子:
假设你在Windows下进行Python开发,Windows会自动在有图片的目录下生成隐藏的缩略图文件,如果有自定义目录,目录下就会有Desktop.ini
文件,因此你需要忽略Windows自动生成的垃圾文件:
1 2 3 4 | # Windows: Thumbs.db ehthumbs.db Desktop.ini |
然后,继续忽略Python编译产生的.pyc
、.pyo
、dist
等文件或目录:
1 2 3 4 5 6 7 | # Python: *.py[cod] *.so *.egg *.egg-info dist build |
加上你自己定义的文件,最终得到一个完整的.gitignore
文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # Windows: Thumbs.db ehthumbs.db Desktop.ini # Python: *.py[cod] *.so *.egg *.egg-info dist build # My configurations: db.ini deploy_key_rsa |
最后一步就是把.gitignore
也提交到Git,就完成了!当然检验.gitignore
的标准是git status
命令是不是说working directory clean
。
使用Windows的童鞋注意了,如果你在资源管理器里新建一个.gitignore
文件,它会非常弱智地提示你必须输入文件名,但是在文本编辑器里“保存”或者“另存为”就可以把文件保存为.gitignore
了。
有些时候,你想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore
忽略了:
1 2 3 4 | $ git add App.class The following paths are ignored by one of your .gitignore files: App.class Use -f if you really want to add them. |
如果你确实想添加该文件,可以用-f
强制添加到Git:
1 | $ git add -f App.class |
或者你发现,可能是.gitignore
写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore
命令检查:
1 2 | $ git check-ignore - v App.class .gitignore:3:*.class App.class |
Git会告诉我们,.gitignore
的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
小结
-
忽略某些文件时,需要编写
.gitignore
; -
.gitignore
文件本身要放到版本库里,并且可以对.gitignore
做版本管理!
以上文章大量参考或转载自: http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000