git笔记 (根据廖雪峰git教程整理)

创建版本库




初始化一个Git仓库,使用git init命令。


添加文件到Git仓库,分两步:


第一步,使用命令git add <file>,注意,可反复多次使用,添加多个文件;


第二步,使用命令git commit,完成。






时光机穿梭




要随时掌握工作区的状态,使用git status命令。


如果git status告诉你有文件被修改过,用git diff可以查看修改内容。








版本回退




HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。


穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。


如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数.


$ git reset --hard HEAD^


上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写成HEAD~100。


要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。


指定回到未来的某个版本:


$ git reset --hard 3628164










工作区和暂存区




git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。








管理修改




现在,你又理解了Git是如何跟踪修改的,每次修改,如果不add到暂存区,那就不会加入到commit中。








撤销修改




命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:


一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;


一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。


总之,就是让这个文件回到最近一次git commit或git add时的状态。


git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。




将暂存区和工作区内容清空:


git reset HEAD file  把暂存区的修改撤销掉(unstage),重新放回工作区


git checkout -- readme.txt   丢弃工作区的修改








删除文件




git rm test.txt


还原rm误删:


rm test.txt


git checkout -- test.txt








远程仓库




把一个已有的本地仓库与git服务器关联


git remote add origin git@github.com:gabencui/learngit.git


git push -u origin master 由于远程库是空的,我们第一次推送master分支时,加上了-u参数


git push origin master 把本地master分支的最新修改推送至GitHub








从远程库克隆




远程库已经准备好后,下一步是用命令git clone克隆一个本地库


git clone git@github.com:gabencui/gitskills.git


要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。


Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。






创建与合并分支




查看分支:git branch


创建分支:git branch <name>


切换分支:git checkout <name>


创建+切换分支:git checkout -b <name>


合并某分支到当前分支:git merge <name>


删除分支:git branch -d <name>








解决冲突




当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。


用git log --graph命令可以看到分支合并图。


git log --graph --pretty=oneline --abbrev-commit






分支管理策略




通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。


如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。




不使用 --no-ff ,以Fast-forward方式提交:


root@ubuntu:/data# git log --graph --pretty=oneline --abbrev-commit | head
*   740499a commit
|\  
| * c2d9a8c commit dev
| * db5c770 commit dev


root@ubuntu:/data# git merge dev1


root@ubuntu:/data# git log --graph --pretty=oneline --abbrev-commit | head
* 54fa0f7 commit dev1
*   740499a commit
|\  
| * c2d9a8c commit dev
| * db5c770 commit dev




使用 --no-ff 提交:


root@ubuntu:/data# git log --graph --pretty=oneline --abbrev-commit | head
* 54fa0f7 commit dev1
*   740499a commit


root@ubuntu:/data# git merge --no-ff -m "merge dev2 with --no-ff" dev2


root@ubuntu:/data# git log --graph --pretty=oneline --abbrev-commit | head
*   0310e83 merge dev2 with --no-ff
|\  
| * b861a11 commit dev2 #此处从分支历史上就可以看出分支信息。
|/  
* 54fa0f7 commit dev1
*   740499a commit








Bug分支




stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:


root@ubuntu:/data# git checkout dev
Switched to branch 'dev'
root@ubuntu:/data# vi readme.txt 
root@ubuntu:/data# git status
On branch dev
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:   readme.txt


no changes added to commit (use "git add" and/or "git commit -a")


root@ubuntu:/data# git stash
Saved working directory and index state WIP on dev: c2d9a8c commit dev
HEAD is now at c2d9a8c commit dev


root@ubuntu:/data# git status
On branch dev
nothing to commit, working directory clean


首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支"issue-101"


修复完成后,切换到master分支,并完成合并,最后删除issue-101分支


回到dev分支干活:


root@ubuntu:/data# git checkout dev
Switched to branch 'dev'
root@ubuntu:/data#  git status
On branch dev
nothing to commit, working directory clean


用git stash list命令查看保存的工作现场:


root@ubuntu:/data# git stash list
stash@{0}: WIP on dev: c2d9a8c commit dev


恢复工作现场有两个办法:


一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;


另一种方式是用git stash pop,恢复的同时把stash内容也删了:


root@ubuntu:/data# git stash pop
On branch dev
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:   readme.txt


no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (bebad162f2368da618f8279dbca625a6f2ab71f8)


再用git stash list查看,就看不到任何stash内容了。


可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:


$ git stash apply stash@{0}








Feature分支(强制删除未合并的分支)


丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除:


root@ubuntu:/data# git checkout -b feature-vulcan
root@ubuntu:/data# touch vulcan.py
root@ubuntu:/data# git add vulcan.py 
root@ubuntu:/data# git commit -m "add feature vulan"
root@ubuntu:/data# git checkout master


root@ubuntu:/data# git branch -d feature-vulcan 
error: The branch 'feature-vulcan' is not fully merged. #提示feature-vulcan分支还没有合并
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.


root@ubuntu:/data# git branch -D feature-vulcan #使用 -D 强制删除未合并的分支
Deleted branch feature-vulcan (was 9b7c1c9).






多人协作




推送分支


$ git push origin master


如果要推送其他分支,比如dev,就改成:


$ git push origin dev


抓取分支


git clone git@github.com:gabencui/learngit.git


现在,你的小伙伴要在dev分支上开发,就必须创建远程origin的dev分支到本地


root@ubuntu:/learngit/learngit# git checkout -b dev origin/dev
fatal: Cannot update paths and switch to branch 'dev' at the same time.
Did you intend to checkout 'origin/dev' which can not be resolved as commit?


因为本地还没有'dev'分支信息,需要先fetch或者pull,git fetch后提示相同错误时,要确定远程git服务器上是否存在dev分支


推送dev分支:


root@ubuntu:~# cd /data
root@ubuntu:/data# git branch
  dev
* master
root@ubuntu:/data# git push origin dev
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:gabencui/learngit.git
 * [new branch]      dev -> dev


同步dev分支:


root@ubuntu:/learngit/learngit# git branch
* master
root@ubuntu:/learngit/learngit# git checkout -b dev origin/dev
fatal: Cannot update paths and switch to branch 'dev' at the same time.
Did you intend to checkout 'origin/dev' which can not be resolved as commit?
root@ubuntu:/learngit/learngit# git fetch                                          #git fetch:相当于是从远程获取最新版本到本地,不会自动merge
From github.com:gabencui/learngit
 * [new branch]      dev        -> origin/dev
root@ubuntu:/learngit/learngit# git checkout -b dev origin/dev #命令创建本地dev分支
Branch dev set up to track remote branch dev from origin.
Switched to a new branch 'dev'
root@ubuntu:/learngit/learngit# git branch
* dev
  master


现在可以在dev分支进行编辑。






一个推送,抓取的过程:


推送:


root@ubuntu:/data# vi readme.txt 
root@ubuntu:/data# cat readme.txt 


...


user2 edit..
user1 edit..
root@ubuntu:/data# git add readme.txt 
root@ubuntu:/data# git commit -m "user1 commit"
[dev e9a5d7e] user1 commit
 1 file changed, 1 insertion(+)
root@ubuntu:/data# git push origin dev
Counting objects: 7, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 287 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To git@github.com:gabencui/learngit.git
   b91c692..e9a5d7e  dev -> dev


抓取:


root@ubuntu:/learngit/learngit# git fetch
root@ubuntu:/learngit/learngit# cat readme.txt 


...


user2 edit..
root@ubuntu:/learngit/learngit# git merge origin/dev
Updating b91c692..e9a5d7e
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
root@ubuntu:/learngit/learngit# cat readme.txt 


...


user2 edit..
user1 edit..


上面的 git fetch 再 git merge origin/dev 相当于 git pull(git pull:相当于是从远程获取最新版本并merge到本地),在实际使用中,git fetch更安全一些,因为在merge前,我们可以查看更新情况,然后再决定是否合并


比较本地的master分支和origin/master分支的差别:


git log -p dev origin/dev


fetch 和 pull 可以指定具体分支:


git fetch origin dev
git pull origin dev




小结


查看远程库信息,使用git remote -v;


本地新建的分支如果不推送到远程,对其他人就是不可见的;


从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;


在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;


建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;


从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。








标签管理






创建标签


命令git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id;


git tag -a <tagname> -m "blablabla..."可以指定标签信息;


git tag -s <tagname> -m "blablabla..."可以用PGP签名标签;


命令git tag可以查看所有标签。






操作标签


命令git push origin <tagname>可以推送一个本地标签;


命令git push origin --tags可以推送全部未推送过的本地标签;


命令git tag -d <tagname>可以删除一个本地标签;


命令git push origin :refs/tags/<tagname>可以删除一个远程标签。






使用GitHub








自定义Git






忽略特殊文件


在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。


可以用-f强制添加到Git:


$ git add -f App.class




忽略文件的原则是:


忽略操作系统自动生成的文件,比如缩略图等;
忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。






配置别名


$ git config --global alias.st status
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch


commit :


git ci -m "this is a commit"




git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"


在配置文件中配置别名:


$ cat .gitconfig
[alias]
    co = checkout
    ci = commit
    br = branch
    st = status






搭建Git服务器




第一步,安装git:


$ sudo apt-get install git
第二步,创建一个git用户,用来运行git服务:


$ sudo adduser git
第三步,创建证书登录:


收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。


第四步,初始化Git仓库:


先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:


$ sudo git init --bare sample.git
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:


$ sudo chown -R git:git sample.git
第五步,禁用shell登录:


出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:


git:x:1001:1001:,,,:/home/git:/bin/bash
改为:


git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。


第六步,克隆远程仓库:


现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:


$ git clone git@server:/srv/sample.git
Cloning into 'sample'...
warning: You appear to have cloned an empty repository.
剩下的推送就简单了。




git使用简易指南:


http://www.bootcss.com/p/git-guide/















































  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值