无常是常

分享技术见解、学习心得和生活感悟

最新文章

我每天使用的11个Git Commands

本文是为我的年轻人(或任何新手)准备的,他们可以有效地使用git命令行,并简要介绍了我如何使用这些命令。
https://medium.com/@mmpatil34/11-git-commands-i-use-daily-9bbd7590c8eb

1. git fetch origin

从特定的仓库拉取所有的branchs/tags, 这里的仓库是“origin”, 我每天从这个命令开始, 它可以让本地和远程仓库状态保持一致.

2. git status

显示当前分支自上次提交到现在的文件改动列表,在切换分支、创建新分支、进行新更改或拉取更改之前, 此命令可以检查是否有文件需要被stash.

3. git checkout

git checkout -b <new branch name> origin/<source branch name>
从特定源分支创建一个新分支,这块的“origin”代表默认仓库.
git checkout — — <name of the file>
当本地有文件变动时,可以使用这个命令丢弃当前改变,恢复文件到之前状态.
git checkout <branch name>
切换本地到指定分支.

4. git pull origin

将更改从远程分支拉到本地分支,并在更改兼容的情况下调用git merge
git pull 和 git fetch的不同之处是: git pull = git fetch + git merge

5. git add

文件修改完成后,就可以使用git add命令将文件添加到特定提交中,使用git status命令可以很方便的获取到要添加指定提交的文件名.

6. git commit

git commit -m "<提交内容的描述>"
提交本地改变,并指定和提交内容相关的描述.

7. git push origin

将本地提交推送到远程存储库,这里的仓库是“origin”.

8. git cherry-pick

1
2
3
a - b - c - d   Master
\
e - f - g Feature

现在将提交f应用到master分支。

1
2
3
4
5
6

# 切换到 master 分支
$ git checkout master

# Cherry pick 操作
$ git cherry-pick f

上面的操作完成以后,代码库就变成了下面的样子。

1
2
3
a - b - c - d - f   Master
\
e - f - g Feature
1
git cherry-pick -m 1 <commit_id>

如果原始提交是一个合并节点,来自于两个分支的合并,那么 Cherry pick 默认将失败,因为它不知道应该采用哪个分支的代码变动。

-m配置项告诉 Git,应该采用哪个分支的变动。它的参数parent-number是一个从1开始的整数,代表原始提交的父分支编号。

上面命令表示,Cherry pick 采用提交commitHash来自编号1的父分支的变动。
一般来说,1号父分支是接受变动的分支(the branch being merged into),2号父分支是作为变动来源的分支(the branch being merged from)。

9. git revert

引入一个新的提交来撤回已经push的提交.

10. git reset — soft HEAD~1

撤消一次本地提交而不会丢失文件中的变更.

11. git reset — hard HEAD~1

撤销一次本地提交并且丢弃文件中的变更.
希望对你有帮助. 感谢阅读😁

本文是为我的年轻人(或任何新手)准备的,他们可以有效地使用git命令行,并简要介绍了我如何使用这些命令。
https://medium.com/@mmpatil34/11-git-commands-i-use-daily-9bbd7590c8eb

1. git fetch origin

从特定的仓库拉取所有的branchs/tags, 这里的仓库是“origin”, 我每天从这个命令开始, 它可以让本地和远程仓库状态保持一致.

2. git status

显示当前分支自上次提交到现在的文件改动列表,在切换分支、创建新分支、进行新更改或拉取更改之前, 此命令可以检查是否有文件需要被stash.

3. git checkout

git checkout -b <new branch name> origin/<source branch name>
从特定源分支创建一个新分支,这块的“origin”代表默认仓库.
git checkout — — <name of the file>
当本地有文件变动时,可以使用这个命令丢弃当前改变,恢复文件到之前状态.
git checkout <branch name>
切换本地到指定分支.

4. git pull origin

将更改从远程分支拉到本地分支,并在更改兼容的情况下调用git merge
git pull 和 git fetch的不同之处是: git pull = git fetch + git merge

5. git add

文件修改完成后,就可以使用git add命令将文件添加到特定提交中,使用git status命令可以很方便的获取到要添加指定提交的文件名.

6. git commit

git commit -m "<提交内容的描述>"
提交本地改变,并指定和提交内容相关的描述.

7. git push origin

将本地提交推送到远程存储库,这里的仓库是“origin”.

8. git cherry-pick

1
2
3
a - b - c - d   Master
\
e - f - g Feature

现在将提交f应用到master分支。

1
2
3
4
5
6

# 切换到 master 分支
$ git checkout master

# Cherry pick 操作
$ git cherry-pick f

上面的操作完成以后,代码库就变成了下面的样子。

1
2
3
a - b - c - d - f   Master
\
e - f - g Feature
1
git cherry-pick -m 1 <commit_id>

如果原始提交是一个合并节点,来自于两个分支的合并,那么 Cherry pick 默认将失败,因为它不知道应该采用哪个分支的代码变动。

-m配置项告诉 Git,应该采用哪个分支的变动。它的参数parent-number是一个从1开始的整数,代表原始提交的父分支编号。

上面命令表示,Cherry pick 采用提交commitHash来自编号1的父分支的变动。
一般来说,1号父分支是接受变动的分支(the branch being merged into),2号父分支是作为变动来源的分支(the branch being merged from)。

9. git revert

引入一个新的提交来撤回已经push的提交.

10. git reset — soft HEAD~1

撤消一次本地提交而不会丢失文件中的变更.

11. git reset — hard HEAD~1

撤销一次本地提交并且丢弃文件中的变更.
希望对你有帮助. 感谢阅读😁

go反向代理quickstart

main.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package main

import (
"context"
"github.com/gorilla/mux"
"github.com/txn2/txeh"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"os/signal"
)

var hostArr = []string{"project-01", "project-02"}

const (
host = "api-dev.deveye.cn"
proxyUrl = "https://api-dev.deveye.cn/"
address = "127.0.0.1"
)

func main() {
hosts, err := txeh.NewHostsDefault()
if err != nil {
panic(err)
}
hosts.AddHosts(address, hostArr)
log.Println(hosts.Save())
r := mux.NewRouter()
r.Use(LoggingHandler, AuthHandler, RecoverHandler)
r.PathPrefix("/").HandlerFunc(ReverseProxy)
srv := &http.Server{
Addr: ":80",
Handler: r,
}
go func() {
if err := srv.ListenAndServe(); err != nil {
log.Println(err)
}
}()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
log.Println(srv.Shutdown(ctx))
hosts.RemoveHosts(hostArr)
log.Println(hosts.Save())
log.Println("shutting down")
os.Exit(0)
}

func ReverseProxy(w http.ResponseWriter, r *http.Request) {
u, err := url.Parse(proxyUrl)
if err != nil {
log.Println(err)
}
proxy := httputil.NewSingleHostReverseProxy(u)
r.Host = host
proxy.ServeHTTP(w, r)
}

middleware.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

import (
"bytes"
"encoding/json"
"errors"
"io/ioutil"
"log"
"net/http"
"time"
)

var loginUrl = proxyUrl + "login/sms"

func LoggingHandler(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
t1 := time.Now()
next.ServeHTTP(w, r)
t2 := time.Now()
log.Printf("[%s] %q %v", r.Method, r.URL.String(), t2.Sub(t1))
}
return http.HandlerFunc(fn)
}

func RecoverHandler(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Printf("Recover from panic: %+v", err)
http.Error(w, http.StatusText(500), 500)
}
}()
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}

func AuthHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token, err := getAccessToken()
if err != nil {
log.Fatalln(err)
}
r.Header.Set("X-Auth-AppId", "10003")
r.Header.Set("X-Auth-Token", token)
next.ServeHTTP(w, r)
})
}

func getAccessToken() (string, error) {
params := map[string]string{
"phone": "15555555551",
"verifyCode": "888888",
"codeId": "111111",
}
marshal, _ := json.Marshal(params)
reader := bytes.NewReader(marshal)
request, _ := http.NewRequest("POST", loginUrl, reader)
request.Header.Add("X-Auth-AppId", "10003")
request.Header.Set("content-type", "application/json")
client := &http.Client{}
do, err := client.Do(request)
if err != nil {
return "", err
}
b, err := ioutil.ReadAll(do.Body)
if err != nil {
return "", err
}
_ = do.Body.Close()
result := &LoginResult{}
if err := json.Unmarshal(b, result); err != nil {
return "", err
}
if result.ErrCode != "0" {
return "", errors.New(result.Message)
}
return result.Data.Token, nil
}

type LoginResult struct {
ErrCode string
Message string
Data struct {
Name string
Token string
Phone string
}
}

main.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package main

import (
"context"
"github.com/gorilla/mux"
"github.com/txn2/txeh"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"os/signal"
)

var hostArr = []string{"project-01", "project-02"}

const (
host = "api-dev.deveye.cn"
proxyUrl = "https://api-dev.deveye.cn/"
address = "127.0.0.1"
)

func main() {
hosts, err := txeh.NewHostsDefault()
if err != nil {
panic(err)
}
hosts.AddHosts(address, hostArr)
log.Println(hosts.Save())
r := mux.NewRouter()
r.Use(LoggingHandler, AuthHandler, RecoverHandler)
r.PathPrefix("/").HandlerFunc(ReverseProxy)
srv := &http.Server{
Addr: ":80",
Handler: r,
}
go func() {
if err := srv.ListenAndServe(); err != nil {
log.Println(err)
}
}()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
log.Println(srv.Shutdown(ctx))
hosts.RemoveHosts(hostArr)
log.Println(hosts.Save())
log.Println("shutting down")
os.Exit(0)
}

func ReverseProxy(w http.ResponseWriter, r *http.Request) {
u, err := url.Parse(proxyUrl)
if err != nil {
log.Println(err)
}
proxy := httputil.NewSingleHostReverseProxy(u)
r.Host = host
proxy.ServeHTTP(w, r)
}

middleware.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

import (
"bytes"
"encoding/json"
"errors"
"io/ioutil"
"log"
"net/http"
"time"
)

var loginUrl = proxyUrl + "login/sms"

func LoggingHandler(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
t1 := time.Now()
next.ServeHTTP(w, r)
t2 := time.Now()
log.Printf("[%s] %q %v", r.Method, r.URL.String(), t2.Sub(t1))
}
return http.HandlerFunc(fn)
}

func RecoverHandler(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Printf("Recover from panic: %+v", err)
http.Error(w, http.StatusText(500), 500)
}
}()
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}

func AuthHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token, err := getAccessToken()
if err != nil {
log.Fatalln(err)
}
r.Header.Set("X-Auth-AppId", "10003")
r.Header.Set("X-Auth-Token", token)
next.ServeHTTP(w, r)
})
}

func getAccessToken() (string, error) {
params := map[string]string{
"phone": "15555555551",
"verifyCode": "888888",
"codeId": "111111",
}
marshal, _ := json.Marshal(params)
reader := bytes.NewReader(marshal)
request, _ := http.NewRequest("POST", loginUrl, reader)
request.Header.Add("X-Auth-AppId", "10003")
request.Header.Set("content-type", "application/json")
client := &http.Client{}
do, err := client.Do(request)
if err != nil {
return "", err
}
b, err := ioutil.ReadAll(do.Body)
if err != nil {
return "", err
}
_ = do.Body.Close()
result := &LoginResult{}
if err := json.Unmarshal(b, result); err != nil {
return "", err
}
if result.ErrCode != "0" {
return "", errors.New(result.Message)
}
return result.Data.Token, nil
}

type LoginResult struct {
ErrCode string
Message string
Data struct {
Name string
Token string
Phone string
}
}