<commit_before>git status
git add .
git commit -m "comment"
git push origin master
git merge dev
git log --pretty=oneline
git reflog
git checkout -b dev
git branch -d dev
git merge --no-ff -m "this is no-ff merge mode" dev
$ git add . && git commit -m "initial drop"
$ git rebase master
$ git status -s

要关联一个远程库，使用命令git remote add origin <EMAIL>:path/repo-name.git；
关联后，使用命令git push -u origin master第一次推送master分支的所有内容；
此后，每次本地提交后，只要有必要，就可以使用命令git push origin master推送最新修改；

git branch命令会列出所有分支，当前分支前面会标一个*号。
$ git checkout -b dev表示创建并切换，相当于以下两条命令：
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
把dev分支的工作成果合并到master分支上：
$ git merge dev
Updating d17efd8..fec145a
Fast-forward
 readme.txt |    1 +
 1 file changed, 1 insertion(+)
因为创建、合并和删除分支非常快，所以Git鼓励你使用分支完成某个任务，合并后再删掉分支，这和直接在master分支上工作效果是一样的，但过程更安全。
创建与合并分支

小结

Git鼓励大量使用分支：
查看分支：git branch
创建分支：git branch <name>
切换分支：git checkout <name>
创建+切换分支：git checkout -b <name>
合并某分支到当前分支：git merge <name>
删除分支：git branch -d <name>

HEAD指向的版本就是当前版本，因此，Git允许我们在版本的历史之间穿梭，使用命令git reset --hard commit_id。
穿梭前，用git log可以查看提交历史，以便确定要回退到哪个版本。
要重返未来，用git reflog查看命令历史，以便确定要回到未来的哪个版本。HEAD指向的版本就是当前版本，因此，Git允许我们在版本的历史之间穿梭，使用命令git reset --hard commit_id。
穿梭前，用git log可以查看提交历史，以便确定要回退到哪个版本。
要重返未来，用git reflog查看命令历史，以便确定要回到未来的哪个版本。

小结
Git分支十分强大，在团队开发中应该充分应用。
合并分支时，加上--no-ff参数就可以用普通模式合并，合并后的历史有分支，能看出来曾经做过合并，而fast forward合并就看不出来曾经做过合并。

分支策略
在实际开发中，我们应该按照几个基本原则进行分支管理：
首先，master分支应该是非常稳定的，也就是仅用来发布新版本，平时不能在上面干活；
那在哪干活呢？干活都在dev分支上，也就是说，dev分支是不稳定的，到某个时候，比如1.0版本发布时，再把dev分支合并到master上，在master分支发布1.0版本；
你和你的小伙伴们每个人都在dev分支上干活，每个人都有自己的分支，时不时地往dev分支上合并就可以了。

当你接到一个修复一个代号101的bug的任务时，很自然地，你想创建一个分支issue-101来修复它，但是，等等，当前正在dev上进行的工作还没有提交：
$ git status
# On branch dev
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   hello.py
#
# 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
#
并不是你不想提交，而是工作只进行到一半，还没法提交，预计完成还需1天时间。但是，必须在两个小时内修复该bug，怎么办？
幸好，Git还提供了一个stash功能，可以把当前工作现场“储藏”起来，等以后恢复现场后继续工作：
$ git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge
现在，用git status查看工作区，就是干净的（除非有没有被Git管理的文件），因此可以放心地创建分支来修复bug。

修复bug时，我们会通过创建新的bug分支进行修复，然后合并，最后删除；
当手头工作没有完成时，先把工作现场git stash一下，然后去修复bug，修复后，再git stash pop，回到工作现场。

用git stash list命令看看：
$ git stash list
stash@{0}: WIP on dev: 6224937 add merge
工作现场还在，Git把stash内容存在某个地方了，但是需要恢复一下，有两个办法：
一是用git stash apply恢复，但是恢复后，stash内容并不删除，你需要用git stash drop来删除；
另一种方式是用git stash pop，恢复的同时把stash内容也删了：

rerere = reuse recorded resolution
它会让Git记住你是如何解决某个文件的两个版本之间的conflict，这样在下次Git遇到同样的文件在相同的两个版本间发生冲突时，可以自动帮你使用相同的方法解决冲突。
如何启用rerere？
git config --global rerere.enabled true

rerere帮我自动处理了conflict，但我已经忘了这个文件conflict的时候是啥样子了。。。能看看conflict的时候的样子吗？
执行git checkout --conflict=merge <path>即可

git pull后提示有文件冲突，则修改有冲突的地方，再git commit -a，git pull xxx, git push xxx。
不像svn，冲突文件修改后还要resolve一下，直接提交就行。



=============start================================= git push 每次都需要输入用户名和密码 ======================================
解决方案：

每次都需要输入用户名和密码是因为你采用的是 https 方式提交代码， 如果采用的是 ssh 方式只需要在版本库中添加用户的 sha 的key就可以实现提交时无需输入用户名和密码。
详细步骤：

步骤1：

如果你的版本库已经用https 方式创建好了，那么就需要先删除原来的提交方式。在终端执行以下指令：

 git remote rm origin
 git remote add origin <EMAIL>:(用户名)/版本库名

这里我提供一下我的具体例子： 
https: https://github.com/用户名/GitTest.git 
ssh: <EMAIL>:用户名/GitTest.git 
我是怎么知道的呢？如果你在创建版本库时选择不创建README.md，系统会提示你创建：

https：
…or create a new repository on the command line
echo # GitTest >> README.md

git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/Sugerming/GitTest.git
git push -u origin master

…or push an existing repository from the command line
git remote add origin https://github.com/Sugerming/GitTest.git
git push -u origin master



ssh:
…or create a new repository on the command line
echo # GitTest >> README.md

git init
git add README.md
git commit -m "first commit"
git remote add origin <EMAIL>:Sugerming/GitTest.git
git push -u origin master


…or push an existing repository from the command line
git remote add origin <EMAIL>:Sugerming/GitTest.git
git push -u origin master

步骤2：

然后这个时候你使用下面指令提交代码：

git push -u origin master

系统会提示：

The authenticity of host 'github.com (192.168.127.12)' can't be established.
RSA key fingerprint is SHA256:<KEY>.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.168.127.12' (RSA) to the list of known h                             osts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights

说明你权限不够。所以这时你需要在本地创建自己的RSA的key。如下：

ssh-keygen -t rsa -C "用户名"

然后系统会问你保存路径等东西，我直接enter跳过了。

Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/AlexYi/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

然后系统会生成一些东西：

Your identification has been saved in /c/Users/AlexYi/.ssh/id_rsa.
Your public key has been saved in /c/Users/AlexYi/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:rxfK05d7oZWpDvQ5dRQM0Na7...
The key's randomart image is:
+---[RSA 2048]----+
|           .o.+. |
|             o o.|
|            .   o|
|               o |
...

最主要的是告诉你，你的可以在：

Your public key has been saved in /c/Users/AlexYi/.ssh/id_rsa.pub

找到这个文件，然后用记事本打开，就可以看到自己的key：

ssh-rsa AAAAB3NzaC1yc2EAAAADA...

步骤3：

然后将生成的rsa 的key添加到版本库中即可，方法： 
打开自己的版本库，点击右边的 Settings 进入配置页。 
然后点击左边导航栏的： Deploy keys 进入添加key页面 
然后点击： Add deploy keys ，将自己的内容输入进去就可以了。 
这样就完成了。

最后继续提交更改的代码，使用：

git push -u origin master

可以提交成功。

补充：

如果要使用 git push简短提交代码：

git push

需要配置 :

git config --global push.default simple

或者：

git config --global push.default matching

区别在于，前者只提交你当前所在的分支，而后者会提交本地所有的分支。具体的自己去查一下就明白了

=============end================================= git push 每次都需要输入用户名和密码 ======================================<commit_msg>more features for git<commit_after>git status
git add .
git commit -m "comment"
git push origin master
git merge dev
git log --pretty=oneline
git reflog
git checkout -b dev
git branch -d dev
git merge --no-ff -m "this is no-ff merge mode" dev
$ git add . && git commit -m "initial drop"
$ git rebase master
$ git status -s
git remote -v

要关联一个远程库，使用命令git remote add origin git@server-name:path/repo-name.git；
关联后，使用命令git push -u origin master第一次推送master分支的所有内容；
此后，每次本地提交后，只要有必要，就可以使用命令git push origin master推送最新修改；

git branch命令会列出所有分支，当前分支前面会标一个*号。
$ git checkout -b dev表示创建并切换，相当于以下两条命令：
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
把dev分支的工作成果合并到master分支上：
$ git merge dev
Updating d17efd8..fec145a
Fast-forward
 readme.txt |    1 +
 1 file changed, 1 insertion(+)
因为创建、合并和删除分支非常快，所以Git鼓励你使用分支完成某个任务，合并后再删掉分支，这和直接在master分支上工作效果是一样的，但过程更安全。
创建与合并分支

小结

Git鼓励大量使用分支：
查看分支：git branch
创建分支：git branch <name>
切换分支：git checkout <name>
创建+切换分支：git checkout -b <name>
合并某分支到当前分支：git merge <name>
删除分支：git branch -d <name>

HEAD指向的版本就是当前版本，因此，Git允许我们在版本的历史之间穿梭，使用命令git reset --hard commit_id。
穿梭前，用git log可以查看提交历史，以便确定要回退到哪个版本。
要重返未来，用git reflog查看命令历史，以便确定要回到未来的哪个版本。HEAD指向的版本就是当前版本，因此，Git允许我们在版本的历史之间穿梭，使用命令git reset --hard commit_id。
穿梭前，用git log可以查看提交历史，以便确定要回退到哪个版本。
要重返未来，用git reflog查看命令历史，以便确定要回到未来的哪个版本。

小结
Git分支十分强大，在团队开发中应该充分应用。
合并分支时，加上--no-ff参数就可以用普通模式合并，合并后的历史有分支，能看出来曾经做过合并，而fast forward合并就看不出来曾经做过合并。

分支策略
在实际开发中，我们应该按照几个基本原则进行分支管理：
首先，master分支应该是非常稳定的，也就是仅用来发布新版本，平时不能在上面干活；
那在哪干活呢？干活都在dev分支上，也就是说，dev分支是不稳定的，到某个时候，比如1.0版本发布时，再把dev分支合并到master上，在master分支发布1.0版本；
你和你的小伙伴们每个人都在dev分支上干活，每个人都有自己的分支，时不时地往dev分支上合并就可以了。

当你接到一个修复一个代号101的bug的任务时，很自然地，你想创建一个分支issue-101来修复它，但是，等等，当前正在dev上进行的工作还没有提交：
$ git status
# On branch dev
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   hello.py
#
# 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
#
并不是你不想提交，而是工作只进行到一半，还没法提交，预计完成还需1天时间。但是，必须在两个小时内修复该bug，怎么办？
幸好，Git还提供了一个stash功能，可以把当前工作现场“储藏”起来，等以后恢复现场后继续工作：
$ git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge
现在，用git status查看工作区，就是干净的（除非有没有被Git管理的文件），因此可以放心地创建分支来修复bug。

修复bug时，我们会通过创建新的bug分支进行修复，然后合并，最后删除；
当手头工作没有完成时，先把工作现场git stash一下，然后去修复bug，修复后，再git stash pop，回到工作现场。

用git stash list命令看看：
$ git stash list
stash@{0}: WIP on dev: 6224937 add merge
工作现场还在，Git把stash内容存在某个地方了，但是需要恢复一下，有两个办法：
一是用git stash apply恢复，但是恢复后，stash内容并不删除，你需要用git stash drop来删除；
另一种方式是用git stash pop，恢复的同时把stash内容也删了：

rerere = reuse recorded resolution
它会让Git记住你是如何解决某个文件的两个版本之间的conflict，这样在下次Git遇到同样的文件在相同的两个版本间发生冲突时，可以自动帮你使用相同的方法解决冲突。
如何启用rerere？
git config --global rerere.enabled true

rerere帮我自动处理了conflict，但我已经忘了这个文件conflict的时候是啥样子了。。。能看看conflict的时候的样子吗？
执行git checkout --conflict=merge <path>即可

git pull后提示有文件冲突，则修改有冲突的地方，再git commit -a，git pull xxx, git push xxx。
不像svn，冲突文件修改后还要resolve一下，直接提交就行。



=============start================================= git push 每次都需要输入用户名和密码 ======================================
解决方案：

每次都需要输入用户名和密码是因为你采用的是 https 方式提交代码， 如果采用的是 ssh 方式只需要在版本库中添加用户的 sha 的key就可以实现提交时无需输入用户名和密码。
详细步骤：

步骤1：

如果你的版本库已经用https 方式创建好了，那么就需要先删除原来的提交方式。在终端执行以下指令：

 git remote rm origin
 git remote add origin <EMAIL>:(用户名)/版本库名

这里我提供一下我的具体例子： 
https: https://github.com/用户名/GitTest.git 
ssh: <EMAIL>:用户名/GitTest.git 
我是怎么知道的呢？如果你在创建版本库时选择不创建README.md，系统会提示你创建：

https：
…or create a new repository on the command line
echo # GitTest >> README.md

git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/Sugerming/GitTest.git
git push -u origin master

…or push an existing repository from the command line
git remote add origin https://github.com/Sugerming/GitTest.git
git push -u origin master



ssh:
…or create a new repository on the command line
echo # GitTest >> README.md

git init
git add README.md
git commit -m "first commit"
git remote add origin <EMAIL>:Sugerming/GitTest.git
git push -u origin master


…or push an existing repository from the command line
git remote add origin <EMAIL>:Sugerming/GitTest.git
git push -u origin master

步骤2：

然后这个时候你使用下面指令提交代码：

git push -u origin master

系统会提示：

The authenticity of host 'github.com (192.168.127.12)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.168.127.12' (RSA) to the list of known h                             osts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights

说明你权限不够。所以这时你需要在本地创建自己的RSA的key。如下：

ssh-keygen -t rsa -C "用户名"

然后系统会问你保存路径等东西，我直接enter跳过了。

Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/AlexYi/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

然后系统会生成一些东西：

Your identification has been saved in /c/Users/AlexYi/.ssh/id_rsa.
Your public key has been saved in /c/Users/AlexYi/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:rxfK05d7oZWpDvQ5dRQM0Na7...
The key's randomart image is:
+---[RSA 2048]----+
|           .o.+. |
|             o o.|
|            .   o|
|               o |
...

最主要的是告诉你，你的可以在：

Your public key has been saved in /c/Users/AlexYi/.ssh/id_rsa.pub

找到这个文件，然后用记事本打开，就可以看到自己的key：

ssh-rsa AAAAB3NzaC1yc2EAAAADA...

步骤3：

然后将生成的rsa 的key添加到版本库中即可，方法： 
打开自己的版本库，点击右边的 Settings 进入配置页。 
然后点击左边导航栏的： Deploy keys 进入添加key页面 
然后点击： Add deploy keys ，将自己的内容输入进去就可以了。 
这样就完成了。

最后继续提交更改的代码，使用：

git push -u origin master

可以提交成功。

补充：

如果要使用 git push简短提交代码：

git push

需要配置 :

git config --global push.default simple

或者：

git config --global push.default matching

区别在于，前者只提交你当前所在的分支，而后者会提交本地所有的分支。具体的自己去查一下就明白了

=============end================================= git push 每次都需要输入用户名和密码 ======================================

不要用git pull，用git fetch和git merge代替它。
1. git fetch：相当于是从远程获取最新版本到本地，不会自动merge
上述过程其实可以用以下更清晰的方式来进行：
git fetch origin master:tmp
git diff tmp 
git merge tmp
2. git pull：相当于是从远程获取最新版本并merge到本地
git pull origin master
上述命令其实相当于git fetch 和 git merge
在实际使用中，git fetch更安全一些
因为在merge前，我们可以查看更新情况，然后再决定是否合并
结束

执行了add,还未执行commit,Git会告诉你，git checkout -- file可以丢弃工作区的修改：$ git checkout -- readme.txt
命令git checkout -- readme.txt意思就是，把readme.txt文件在工作区的修改全部撤销，这里有两种情况：
一种是readme.txt自修改后还没有被放到暂存区，现在，撤销修改就回到和版本库一模一样的状态；
一种是readme.txt已经添加到暂存区后，又作了修改，现在，撤销修改就回到添加到暂存区后的状态。
总之，就是让这个文件回到最近一次git commit或git add时的状态

git checkout . #本地所有修改的。没有的提交的，都返回到原来的状态
git stash #把所有没有提交的修改暂存到stash里面。可用git stash pop回复。
git reset --hard HASH #返回到某个节点，不保留修改。
git reset --soft HASH #返回到某个节点。保留修改

git客户端工具SmartGit

http://blog.jobbole.com/87700/
如何在 Git 里撤销(几乎)任何操作
撤销一个“已公开”的改变

场景: 你已经执行了 git push, 把你的修改发送到了 GitHub，现在你意识到这些 commit 的其中一个是有问题的，你需要撤销那一个 commit.

方法: git revert <SHA>

原理: git revert 会产生一个新的 commit，它和指定 SHA 对应的 commit 是相反的（或者说是反转的）。如果原先的 commit 是“物质”，新的 commit 就是“反物质” — 任何从原先的 commit 里删除的内容会在新的 commit 里被加回去，任何在原先的 commit 里加入的内容会在新的 commit  里被删除。

这是 Git 最安全、最基本的撤销场景，因为它并不会改变历史 — 所以你现在可以  git push 新的“反转” commit 来抵消你错误提交的 commit。

修正最后一个 commit 消息

场景: 你在最后一条 commit 消息里有个笔误，已经执行了 git commit -m "Fxies bug #42"，但在 git push 之前你意识到消息应该是 “Fixes bug #42″。

方法: git commit --amend 或 git commit --amend -m "Fixes bug #42"

原理: git commit --amend 会用一个新的 commit 更新并替换最近的 commit ，这个新的 commit 会把任何修改内容和上一个 commit 的内容结合起来。如果当前没有提出任何修改，这个操作就只会把上次的 commit 消息重写一遍。

撤销“本地的”修改

场景: 一只猫从键盘上走过，无意中保存了修改，然后破坏了编辑器。不过，你还没有 commit 这些修改。你想要恢复被修改文件里的所有内容 — 就像上次 commit 的时候一模一样。

方法: git checkout -- <bad filename>

原理: git checkout 会把工作目录里的文件修改到 Git 之前记录的某个状态。你可以提供一个你想返回的分支名或特定 SHA ，或者在缺省情况下，Git 会认为你希望 checkout 的是 HEAD，当前 checkout 分支的最后一次 commit。

记住：你用这种方法“撤销”的任何修改真的会完全消失。因为它们从来没有被提交过，所以之后 Git 也无法帮助我们恢复它们。你要确保自己了解你在这个操作里扔掉的东西是什么！（也许可以先利用 git diff 确认一下）

 

重置“本地的”修改

场景: 你在本地提交了一些东西（还没有 push），但是所有这些东西都很糟糕，你希望撤销前面的三次提交 — 就像它们从来没有发生过一样。

方法: git reset <last good SHA> 或 git reset --hard <last good SHA>

原理: git reset 会把你的代码库历史返回到指定的 SHA 状态。 这样就像是这些提交从来没有发生过。缺省情况下， git reset 会保留工作目录。这样，提交是没有了，但是修改内容还在磁盘上。这是一种安全的选择，但通常我们会希望一步就“撤销”提交以及修改内容 — 这就是 --hard 选项的功能。

在撤销“本地修改”之后再恢复

场景: 你提交了几个 commit，然后用 git reset --hard 撤销了这些修改（见上一段），接着你又意识到：你希望还原这些修改！

方法: git reflog 和 git reset 或 git checkout

原理: git reflog 对于恢复项目历史是一个超棒的资源。你可以恢复几乎 任何东西 — 任何你 commit 过的东西 — 只要通过 reflog。

你可能已经熟悉了 git log 命令，它会显示 commit 的列表。 git reflog 也是类似的，不过它显示的是一个 HEAD 发生改变的时间列表.

一些注意事项：

它涉及的只是 HEAD 的改变。在你切换分支、用 git commit 进行提交、以及用 git reset 撤销 commit 时，HEAD 会改变，但当你用  git checkout -- <bad filename> 撤销时（正如我们在前面讲到的情况），HEAD 并不会改变 — 如前所述，这些修改从来没有被提交过，因此 reflog 也无法帮助我们恢复它们。
git reflog 不会永远保持。Git 会定期清理那些 “用不到的” 对象。不要指望几个月前的提交还一直躺在那里。
你的 reflog 就是你的，只是你的。你不能用 git reflog 来恢复另一个开发者没有 push 过的 commit。
那么…你怎么利用 reflog 来“恢复”之前“撤销”的 commit 呢？它取决于你想做到的到底是什么：

如果你希望准确地恢复项目的历史到某个时间点，用 git reset --hard <SHA>
如果你希望重建工作目录里的一个或多个文件，让它们恢复到某个时间点的状态，用 git checkout <SHA> -- <filename>
如果你希望把这些 commit 里的某一个重新提交到你的代码库里，用 git cherry-pick <SHA>


小结

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

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

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

命令git tag可以查看所有标签。
{'fraction_non_alphanumeric': 0.1075282883118582, 'fraction_numerical': 0.012492641768591798, 'mean_word_length': 5.341766901700539, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 51, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4449260', 'n_tokens_mistral': 8793, 'n_tokens_neox': 9390, 'n_words': 1533}