[项目工具>git]
目录
一. 创建版本库
二. 版本控制基础知识
- status 和 diff命令
- 版本控制相关命令
- 工作区和暂存区
三. 管理修改
- 修改的一般方法
- 撤销修改
- 删除文件
四. 远程仓库
五. 分支管理
- 分支冲突
- 关于快速合并
- Bug分支
- 删除未合并的分支
六. 多人协作的相关问题
- 推送分支
- 抓取分支
- rebase
七. 标签管理
八. 忽略特殊文件
一. 创建版本库
关于基本的init .add, commit命令
//创建目录
$ mkdir project
$ cd project
//在该目录中创建仓库
$ git init
Initialized empty Git repository in /mnt/d/nucleus/0-1_Project/tools/project/.git/
//在仓库中增加文本
$ vim readme.md
# this is a opensource project
> by crepuscule.xyz
//将文件添加到仓库
$ git add readme.md
//查看git状态
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: readme.md
//使用git commit将文件提交仓库,-m参数表示本次提交的说明
$ git commit -m "add a readme file"
[master (root-commit) c8d98aa] add a readme file
1 file changed, 2 insertions(+)
create mode 100644 reaeme.md
二. 版本控制基础知识
- status 和 diff命令
//修改readme.md为以下内容
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
//查看状态
$ 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: readme.md
no changes added to commit (use "git add" and/or "git commit -a")
//可以使用git diff查看上次修改的内容
$ git diff
diff --git a/readme.md b/readme.md
index e19f174..0e05c8d 100644
--- a/readme.md
+++ b/readme.md
@@ -1,2 +1,2 @@
-# this is a opensource progject
-> by crepuscule.xyz
+# this is a big opensource progject
+> by blog.crepuscule.xyz
//同样地提交修改并commit并查看提交后的状态
$ git add readme.md && git commit -m "add big and blog" && git status
[master 5df3411] add big and blog
1 file changed, 2 insertions(+), 2 deletions(-)
On branch master
nothing to commit, working tree clean
- 版本控制相关命令
介绍git reset ,reflog等git版本回退,前进的相关命令
//使用log命令得知git 仓库中文件的改动记录
$ git log
commit 5df3411a2858b00a5b9717818304bfdd9bb3493a
Author: crepuscule <twilight_wang@163.com>
Date: Tue Aug 6 14:52:42 2019 +0800
add big and blog
commit c8d98aad0087a970b8070d7f89c51c3dcbc00850
Author: crepuscule <twilight_wang@163.com>
Date: Tue Aug 6 14:39:17 2019 +0800
add a readme file
//git log 的--pretty=oneline参数会输出精简化的信息
$ git log --pretty=oneline
5df3411a2858b00a5b9717818304bfdd9bb3493a add big and blog
c8d98aad0087a970b8070d7f89c51c3dcbc00850 add a readme file
//git中,HEAD表示当前版本,前一个版本是HEAD^,前n各版本是HEAD~n
//使用reset命令将版本回退到想要的版本
$ git reset -- hard HEAD^
HEAD is now at 5df3411 add big and blog
$ cat readme.txt
# this is a opensource progject
> by crepuscule.xyz
//通过命令行中命令记录,可以了解到后一个版本(最新版本)的commit id,通过这个id,又可以使得版本前进到目标版本。如果已经丢失命令行命令记录,可以通过git的reflog命令查看git之前的命令记录
$ git reflog
5df3411 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
bcd23dc HEAD@{1}: commit: add big and blog
5df3411 (HEAD -> master) HEAD@{2}: commit: add big and blog
c8d98aa HEAD@{3}: commit (initial): add a readme file
//得知最新版本commit id为bcd23dc,通过git reset --hard commit id
$ git reset --hard bcd23dc
HEAD is now at bcd23dc add big and blog
- 工作区和暂存区
工作区就是项目目录,如本笔记中项目目录project
工作区中的隐藏目录.git就是git的版本库。它存储了git中极为重要的stage(或index)的暂存区。以及git 自动创建的第一个分支master,以及只想master的一个指针HEAD。
使用git add命令实际上是将文件的修改添加进暂存区,使用git commit目录实际上是将暂存区所有内容提交到当前分支。
可以多次使用git add命令将工作区的又改动文件添加到暂存区,然后使用git commit命令将所有暂存区内容一并提交到分支。一旦提交完成,整个暂存区将被置为空,即"working tree clean"。
三. 管理修改
- 修改的一般方法
所有的修改都需要先add再commit
//给readme.txt 增加一行
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
//然后add并查看状态
$ git add readme.md && git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.md
//再修改reamde.md
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6.2019
//再次提交
$ git commit -m "add time"
[master 812053a] add time
1 file changed, 1 insertion(+)
//再查看状态
$ 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: readme.md
no changes added to commit (use "git add" and/or "git commit -a")
//即第二次的改动并没有被提交,这是由于第二次没有后执行git add没有将修改添加进入缓存区。
//提交后可以用git diff HEAD --readme.md命令查看工作区和版本库里最新版本区别:
$ git diff HEAD -- readme.md
diff --git a/readme.md b/readme.md
index d8b1223..785c600 100644
--- a/readme.md
+++ b/readme.md
@@ -1,3 +1,3 @@
# this is a big opensource progject
> by blog.crepuscule.xyz
-created at 8.6
+created at 8.6.2019
//所以对于这个问题,可以再进行一次git add然后commit,也可以在修改时一起修改最后一并add和commit。
- 撤销修改
假设修改了readme.md
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6.2019
useless modify
没有add之前,使用git checkout -- readme.md将文件工作区内的修改全部撤销。
$ git checkout -- readme.md
//再次查看status,修改已经被撤销
$ git status
On branch master
nothing to commit, working tree clean
$ cat readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
如果已经add之后,可用git reset HEAD filename 将暂存区修改add,然后再撤销工作区修改
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
useless modification
$ git add readme.md
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.md
$ git reset HEAD readme.md
Unstaged changes after reset:
M readme.md
$ 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: readme.md
no changes added to commit (use "git add" and/or "git commit -a")
//即使用这个命令撤销了add的过程,将重新放回工作区。
//此时可以再使用checkout -- filename 命令,丢弃其再工作区的修改
$ git checkout -- readme.md
//此时工作修改已经被撤销
$ git status
On branch master
nothing to commit, working tree clean
$ cat readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
总结
- 如果只是修改了工作区某文件内容,直接撤销工作区修改,使用git checkout -- filename
- 如果修改了并且使用add添加进入了暂存区,那么需要使用git reset HEAD filename将其移回工作区,然后使用1中的方法撤销工作区修改
- 如果已经提交,那么需要版本回退。
- 删除文件
$ vim temp.txt
temp file
$ git add temp.txt && git commit -m "add temp file"
[master b45ca35] add temp file
1 file changed, 1 insertion(+)
create mode 100644 temp.txt
//假如在文件系统中直接删了这个文件(相当于未git add之前的修改)
$ rm temp.txt
//则git 会告知它的改动
$ 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: temp.txt
no changes added to commit (use "git add" and/or "git commit -a")
//1. 此时可以确定这个删除,使用git rm删除并git commit(相当于git add和commit)
$ git rm temp.txt
rm 'temp.txt'
$ git commit -m "remove temp file"
[master 1385c3a] remove temp file
1 file changed, 1 deletion(-)
delete mode 100644 temp.txt
$ git status
On branch master
nothing to commit, working tree clean
//2. 或者是删错了,并不是想删除,这时可以使用git checkout -- temp.txt撤销提交,用版本库版本替换工作区版本。(相当于撤销工作区修改)
$ git checkout -- temp.txt
//再次查看发现temp.txt又回来了
$ ls
readme.md temp.txt
四. 远程仓库
先在github上创建一个空的repository,名为project。
//接着在本地仓库下运行命令,使得本地仓库与远程仓库建立连接
$ git remote add origin git@github.com:crepuscule/project.git(已经绑定密钥)
或者
$ git remote add origin https://github.com/crepuscule/project.git (随时可用)
接着就可以将本地库内容推送到远程仓库中
$ git push -u origin master
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
Counting objects: 18, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (18/18), 1.54 KiB | 42.00 KiB/s, done.
Total 18 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), done.
To https://github.com/crepuscule/project.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
由于远程库是空的,第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
//当成功上传远程库后,以后只是本地库做修改提交远程库,只需要运行以下命令。
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
complete!
$git push origin master
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 310 bytes | 34.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/crepuscule/project.git
67451b8..66b7661 master -> master
总结:
- 先使用git remote add origin xxx关联远程仓库
- 再使用git push -u origin master第一次推送
- 之后使用git push origin master即可推送
五. 分支管理
分支功能是为了使团队各个成员可以在别人看不到的分支上进行开发,不影响他人工作,直到完成自己的开发再一次性合并到主分支。
下面通过例子说明这个问题:
//首先创建dev分支,随即切换到该分支
$ git checkout -b dev
Switched to a new branch 'dev'
//上述命令是下面两个命令的简写
$ git branch dev && git checkout dev
//使用branch命令可以查看当前分支
$ git branch
* dev
master
//接着在dev分支上进行修改并提交
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
complete!
this is the dev version!
//提交
$ git add readme.md && git commit -m "branch dev first"
[dev 9809e74] branch dev first
1 file changed, 1 insertion(+)
//此时dev工作完成,需要切回到主分支
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
//此时这个文件不会有刚才多加的一行
$ cat readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
complete!
//分支关系如图所示:
HEAD\
|master
*----*----*----*-------------*
|dev
//现在再将dev合并到master分支上
$ git merge dev
Updating 66b7661..9809e74
Fast-forward
readme.md | 1 +
1 file changed, 1 insertion(+)
//现在reademe.md文件就直接快进到dev分支的版本了
$ cat readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
complete!
this is the dev version!
//此时可以选择删除dev分支,因为它已经和master指向内容完全相同
$ git branch -d dev
Deleted branch dev (was 9809e74).
- 分支冲突
//创建新的feature1分支
$ git checkout -b feature1
Switched to a new branch 'feature1'
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
complete!
this is the dev version!
this will be confilt content1
//并提交该分支
$ git add readme.md && git commit -m "add feature1"
[feature1 b50a73d] add feature1
1 file changed, 1 insertion(+)
//再切回master分支
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Git自动提示当前master分支比远程的master分支要超前1个提交。
//改动master分支最后一行
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
complete!
this is the dev version!
master confilt!
//提交
$ git add readme.md && git commit -m "add master confilt"
[master 4faa4f9] add master confilt
1 file changed, 1 insertion(+)
//现在的分支关系如图所示:
HEAD\
|master
*----*----*----*-------------*
\
------------*
|feature1
//此时无法快速合并,可能需要解决冲突
$ git merge feature1
Auto-merging readme.md
CONFLICT (content): Merge conflict in readme.md
Automatic merge failed; fix conflicts and then commit the result.
//确实发生了冲突,此时通过status命令可以查看冲突的文件
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.md
no changes added to commit (use "git add" and/or "git commit -a")
//可以直接查看reademe.md内容来手动解决冲突
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
complete!
this is the dev version!
<<<<<<< HEAD
master confilt!
=======
this will be confilt content1
>>>>>>> feature1
//手动合并
$ vim readme.md
# this is a big opensource progject
> by blog.crepuscule.xyz
created at 8.6
complete!
this is the dev version!
master will not be confilt content
//再提交
$ git add readme.md && git commit -m "conflict fixed"
[master e855be4] conflict fixed
//使用log命令查看分支合并情况
$ git log --graph
* commit e855be448d429d2f5908a2d7e2c0f46515d7c056 (HEAD -> master)
|\ Merge: 4faa4f9 b50a73d
| | Author: crepuscule <twilight_wang@163.com>
| | Date: Tue Aug 6 21:12:26 2019 +0800
| |
| | conflict fixed
| |
| * commit b50a73d4100eddfb51a71ce59575c233229bf48f
| | Author: crepuscule <twilight_wang@163.com>
| | Date: Tue Aug 6 21:03:36 2019 +0800
| |
| | add feature1
| |
* | commit 4faa4f914198ec360c8deadf3050bea33368ebde
|/ Author: crepuscule <twilight_wang@163.com>
| Date: Tue Aug 6 21:06:31 2019 +0800
|
| add master confilt
|
* commit 9809e742d5850e6c9aab39291e529670abb8d497
| Author: crepuscule <twilight_wang@163.com>
| Date: Tue Aug 6 20:28:18 2019 +0800
|
| branch dev first
|
* commit 66b7661b11f2149e9823b70e02664844c96310b1 (origin/master)
| Author: crepuscule <twilight_wang@163.com>
| Date: Tue Aug 6 17:18:21 2019 +0800
|
| complete
|
* commit 67451b8d223bd995d33ea39209ae817bef9ca68f
| Author: crepuscule <twilight_wang@163.com>
| Date: Tue Aug 6 16:44:48 2019 +0800
|
| add temp2 file
|
* commit 1385c3af893e9e5ccbe4b6193eb83dddc7ce8f53
| Author: crepuscule <twilight_wang@163.com>
| Date: Tue Aug 6 16:41:27 2019 +0800
|
| remove temp file
:
//或者精简模式
$ git log --graph --pretty=oneline --abbrev-commit
* e855be4 (HEAD -> master) conflict fixed
|\
| * b50a73d (feature1) add feature1
* | 4faa4f9 add master confilt
|/
* 9809e74 branch dev first
* 66b7661 (origin/master) complete
* 67451b8 add temp2 file
* 1385c3a remove temp file
* b45ca35 add temp file
* 812053a add time
* bcd23dc add big and blog
* 5df3411 add big and blog
* c8d98aa add a readme file
//此时已经成功合并,删除feature1分支即可
$ git branch -d feature1
Deleted branch feature1 (was b50a73d).
- 关于快速合并
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而如果不是用该参数则git可能自动使用fast forward合并,这样就看不出来曾经做过合并。依自己的需求选择。
$ git checkout -b dev
Switched to a new branch 'dev'
$ vim readme.md
$ git add readme.md && git commit -m "new dev branch"
[dev d38139a] new dev branch
1 file changed, 1 insertion(+), 1 deletion(-)
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 4 commits.
(use "git push" to publish your local commits)
//使用普通模式合并,这是没有冲突,但是会在master上重新创建一个commit,这样在log中就可以显示出这里曾经合并过。
$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
//再查看log命令
$ git log --graph
* commit f8b2792ed428ddee3716cddb93823cdf73ec0727 (HEAD -> master)
|\ Merge: e855be4 d38139a
| | Author: crepuscule <twilight_wang@163.com>
| | Date: Tue Aug 6 21:29:01 2019 +0800
| |
| | merge with no-ff
| |
| * commit d38139a0ee4b4524994cc7491b0013abe63bb5e4 (dev)
|/ Author: crepuscule <twilight_wang@163.com>
| Date: Tue Aug 6 21:28:18 2019 +0800
|
| new dev branch
|
* commit e855be448d429d2f5908a2d7e2c0f46515d7c056
|\ Merge: 4faa4f9 b50a73d
| | Author: crepuscule <twilight_wang@163.com>
| | Date: Tue Aug 6 21:12:26 2019 +0800
| |
| | conflict fixed
....
//不使用快速合并的支关系如图所示:
HEAD\
|master
*----*----*----*-------------*
\ /
-----*----
|dev
//区别也就是多了一个master提交而已,Fast Forward模式直接将dev的提交作为master的一个提交,而这里master自己建了一个提交。
- Bug分支
在当前分支工作未完成,尚不可提交的前提下,如果需要新建一分支用于修改bug或者其他紧急事件,则可以使用stash功能暂存工作现场,这样可以清空工作区,然后便可创建其他分支做更要紧的事情。
//首先需要开发一个新特性,所以创建自己的分支并进行开发工作
$ git checkout -b crepuscule
Switched to a new branch 'crepuscule'
$ vim main.py
//此时接到bug修复通知,要求先修复bug再继续开发,所以首先将工作区文件加入缓存区,然后stash保存现场
$ git status
On branch crepuscule
Untracked files:
(use "git add <file>..." to include in what will be committed)
main.py
nothing added to commit but untracked files present (use "git add" to track)
$ git add --all
$ git stash
Saved working directory and index state WIP on crepuscule: f8b2792 merge with no-ff
//此时再查看status就是clear的
$ git status
On branch crepuscule
nothing to commit, working tree clean
//紧接着回到主分支,创建新的bug分支修复bug
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
$ git checkout -b issue-101
Switched to a new branch 'issue-101'
$ vim readme.md
//修复完成提交
$ git add readme.md && git commit -m "issue-101:progject->project"
[issue-101 1c78fde] issue-101:progject->project
1 file changed, 1 insertion(+), 1 deletion(-)
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
//bug修复完成分支合并到master分支
$ git merge --no-ff -m "merged bug fix 101:project" issue-101
Merge made by the 'recursive' strategy.
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
//到此bug修复结束,继续回到crepuscule分支上进行开发
$ git checkout crepuscule
Switched to branch 'crepuscule'
//回到此会发现工作区和缓存区是干净的,之前添加的文件main.py也不见了,但是其实工作现场被保存了,需要恢复
$ git status
On branch crepuscule
nothing to commit, working tree clean
$ ls
readme.md temp2.txt
//先用stash list命令列出所有stash内容
$ git stash list
stash@{0}: WIP on crepuscule: f8b2792 merge with no-ff
//使用stash apply命令恢复之后用stash drop删除,这里可以看到工作现场已经恢复,main.py已经回来了
$ git stash apply
On branch crepuscule
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: main.py
$ git status
On branch crepuscule
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: main.py
$ ls
main.py readme.md temp2.txt
//或者直接使用stash pop命令,恢复并删除stash
$ git stash pop
On branch crepuscule
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: main.py
Dropped refs/stash@{0} (f8823839e81775f5ee1d432714cc9a56829573ea)
//有多个stash时,使用以下命令恢复
$ git stash apply stash@{0}
- 删除未合并的分支
未合并的分支不能使用普通的-d命令删除,这是git的保护措施。然而,如果确实需要删除,则要使用-D参数方可强制删除。
六. 多人协作的相关问题
查看远程库信息,使用remote命令或remote -v命令更详细查看
$ git remote
origin
$ git remote -v
origin https://github.com/crepuscule/project.git (fetch)
origin https://github.com/crepuscule/project.git (push)
- 推送分支
推送分支时要指定分支名称
$ git push origin crepuscule
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
Counting objects: 16, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (16/16), done.
Writing objects: 100% (16/16), 1.47 KiB | 100.00 KiB/s, done.
Total 16 (delta 6), reused 0 (delta 0)
remote: Resolving deltas: 100% (6/6), done.
remote:
remote: Create a pull request for 'crepuscule' on GitHub by visiting:
remote: https://github.com/crepuscule/project/pull/new/crepuscule
remote:
To https://github.com/crepuscule/project.git
* [new branch] crepuscule -> crepuscule
- 抓取分支
有些时候,线上版本已经超越本地版本几个提交,需要先抓取最新分支与自己的分支合并,然后再次推送
//多人协作时,他人从远程仓库clone项目默认只有master分支
$ git clone https://github.com/crepuscule/project.git
Cloning into 'project'...
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
remote: Enumerating objects: 37, done.
remote: Counting objects: 100% (37/37), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 37 (delta 10), reused 36 (delta 9), pack-reused 0
Unpacking objects: 100% (37/37), done.
$ git branch
* master
//如果要在其他分支上开发,则需要使用下面命令创建本地的其他分支:
$ git checkout -b crepuscule origin/crepuscule
Branch 'crepuscule' set up to track remote branch 'crepuscule' from 'origin'.
Switched to a new branch 'crepuscule'
//然后在此本地库中进行开发,时不时push到远程服务器上。比如
//但是如果他人已经在这次推送之前推送了新的版本,这次的推送必定不会成功,因为远程仓库上的当前版本已经超前本地的当前版本了。
$ git push origin crepuscule
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
To https://github.com/crepuscule/project.git
! [rejected] crepuscule -> crepuscule (fetch first)
error: failed to push some refs to 'https://github.com/crepuscule/project.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.
//所以需要首先pull下仓库中最新的crepusucle分支代码,解决冲突后再次推送。
$ git pull
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 0), reused 4 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.
From https://github.com/crepuscule/project
f8b2792..5065b95 crepuscule -> origin/crepuscule
Merge made by the 'recursive' strategy.
main.py | 2 ++
students.sql | 1 +
2 files changed, 3 insertions(+)
create mode 100644 main.py
create mode 100644 students.sql
//这个例子中没有冲突,直接合并了分支,直接再次push即可
$ git push origin crepuscule
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 522 bytes | 261.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To https://github.com/crepuscule/project.git
5065b95..15f64e9 crepuscule -> crepuscule
总结:多人协作的模式:
- 首先,可以试图用git push origin <branch-name>推送自己的修改;
- 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
- 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再次使用git push origin <branch-name>推送就能成功!
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>即可
- rebase
rebase操作可以把本地未push的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
具体可以参考博客文章://www.greatytc.com/p/6960811ac89c,讲的很好。
七. 标签管理
取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 8 commits.
(use "git push" to publish your local commits)
$ git tag v1.0
$ git tag
v1.0
$ git log --pretty=oneline --abbrev-commit
d97f856 (HEAD -> master, tag: v1.0) merged bug fix 101:project
1c78fde (issue-101) issue-101:progject->project
f8b2792 merge with no-ff
d38139a (dev) new dev branch
e855be4 conflict fixed
4faa4f9 add master confilt
b50a73d add feature1
9809e74 branch dev first
66b7661 (origin/master) complete
67451b8 add temp2 file
1385c3a remove temp file
b45ca35 add temp file
812053a add time
bcd23dc add big and blog
5df3411 add big and blog
c8d98aa add a readme file
//可以看到complete对应的提交的commit id,用此id即可补打标签
$ git tag v0.5 66b7661
//也可以给标签加上说明,加上-a -m参数即可
$ git tag -a v0.0 -m "new project" c8d98aad0087a
//用show命令查看标签的具体信息
$ git show v0.0
tag v0.0
Tagger: crepusucle <crepusucle@gmail.com>
Date: Wed Aug 7 09:26:56 2019 +0800
new project
commit c8d98aad0087a970b8070d7f89c51c3dcbc00850 (tag: v0.0)
Author: crepuscule <twilight_wang@163.com>
Date: Tue Aug 6 14:39:17 2019 +0800
add a readme file
diff --git a/reademe.md b/reademe.md
new file mode 100644
index 0000000..e19f174
--- /dev/null
+++ b/reademe.md
@@ -0,0 +1,2 @@
+# this is a opensource progject
+> by crepuscule.xyz
//也可以删除标签
git tag -d v0.5
Deleted tag 'v0.5' (was 66b7661)
//也可以将标签推送到远程
$ git push origin v1.0
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
Enumerating objects: 22, done.
Counting objects: 100% (22/22), done.
Delta compression using up to 4 threads
Compressing objects: 100% (20/20), done.
Writing objects: 100% (20/20), 1.82 KiB | 186.00 KiB/s, done.
Total 20 (delta 8), reused 0 (delta 0)
remote: Resolving deltas: 100% (8/8), done.
To https://github.com/crepuscule/project.git
* [new tag] v1.0 -> v1.0
//一次性推送所有本地标签
$ git push origin --tags
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 157 bytes | 157.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To https://github.com/crepuscule/project.git
* [new tag] v0.0 -> v0.0
//已经推送的标签如要删除则先在本地删除
$ git tag -d v0.0
Deleted tag 'v0.0' (was c924a0b)
//然后将改动推送到远程
$ git push origin :refs/tags/v0.0
Username for 'https://github.com': crepuscule
Password for 'https://crepuscule@github.com':
To https://github.com/crepuscule/project.git
- [deleted] v0.0
八. 忽略特殊文件
在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
忽略文件的原则是:
1.忽略操作系统自动生成的文件,比如缩略图等;
2.忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
3.忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
比如,进行Java开发,.gitignore文件应该为:
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
接着将.gitignore也提交到git即可。用status命令查看即可知道是否成功。
有时添加文件无法添加,有可能是被.gitignore忽略了。此时可以用-f参数强制添加,即使用命令git add -f xxxx.xxx
。
$ git add xxx.class
The following paths are ignored by one of your .gitignore files:
xxx.class
Use -f if you really want to add them.
$ git add -f xxx.class
$ ls
readme.md temp2.txt xxx.class
也可以修改规则。查看哪条规则有问题可以用git check-ignore -v xxx.xxx
则git会告知那条规则导致xxx.xxx文件无法加入。
$ vim App.class
$ git check-ignore -v App.class
.gitignore:2:*.class App.class