git入门教程

背景

这篇文章汇总了我平时用到的git相关知识和命令,同时记录了我遇到的疑难点和答案,力求从下载git到学会使用一文解决。在撰写本文的过程中,也参考了许多网页和资料,将在文后参考资料小节全部列出。

包含内容

读完本文,将可以解决以下问题:
git如何配置,如何将本机和github通过密钥关联
git如何建立本地版本库,如何与github或gitee等远程仓库连接,如何同时与github和gitee的远程仓库连接。
git如何推到远程仓库。
git如何建立分支,如何切换分支,如何合并分支。
git如何回退到上一个版本,有些文件改错了,不知道改了哪些,如何放弃掉本地的更改。

1 git配置

1、设置用户名和邮箱(--global 为全局参数,表明本地所有Git仓库都会使用这个配置)

git config --global user.name "yourname"
git config --global user.email "your_email@youremail.com"

2、生成密钥(SSH key)

ssh-keygen -t rsa -C "your_email@youremail.com"

967677-20180127235546537-326832952.png
3、在github中添加密钥。
将上一步骤生成的密钥即.ssh/id_rsa.pub中内容全部复制。在github的 Settings-->SSH and GPG keys-->New SSH key,key中粘贴复制的内容(Title自定义)。

2 创建版本库并连接远程仓库

1、先来了解git的工作流。
Screenshot from 2021-06-13 16-26-56.png
git的工作过程就是,自己修改了本地目录中的内容,然后通过命令提交到暂存区,然后通过命令提交HEAD,它指向最后一次提交的结果,然后通过命令提交到远程仓库。
2、进入自己项目文件夹,输入git init,也就是在本地建立了新的仓库。
3、连接远端仓库。首先需要先在github或者gitee建立一个仓库,然后使用以下命令和远端仓库建立连接。

git remote add origin git@github.com:yourName/repositoryname.git  #通过ssh方式(推荐,因为我们前面已经配置了ssh)
git remote add origin https://github.com/yourName/repositoryname.git  #通过https方式

这里有人就会问了,后面这个地址怎么得到呢?很简单,只需要在github或者gitee的右上角,选择下载代码,里面选择ssh,然后把地址复制下来就好了。如图所示大概位置。
Screenshot from 2021-06-13 16-34-35.png
这里注意,这个命令里面的origin是你自己起的名字,可以任意改。如果要同时将本地仓库和github与gitee仓库连接起来的话,那就一个用origin1,一个用origin2就好了,执行两遍上面的命令,那就是分别和github与gitee建立了连接。

3 如何推到远端仓库

执行以下命令,分别将修改过的文件(在本地目录中),提交到暂存区,然后提交到HEAD,然后提交到远端仓库。

git add <file>        将文件添加到暂存区,如果要将工作目录中所有的文件都提交到暂存区,可以直接用git add .
git commit -m "commnet"   提交更改,添加备注信息(此时将暂存区的信息提交到本地HEAD)
git push origin master    将本地仓库的文件push到远程仓库(若 push 不成功,可加 -f 进行强推操作)

4 如何建立、切换、合并分支

有时候,我们需要开发新的特性,不要直接在主分支上开发,而是应该建立一个新的分支,然后在新的分支上开发,最后与主分支合并。
1、使用以下命令建立并切换到新的分支。

git checkout -b branch_name

2、使用以下命令切换分支

git chceckout branch_name

3、将其他分支合并到当前分支使用以下命令。

git merge branch_name_you_want_to_merge

5 如何回退版本

1、使用git log查到你想回退版本的id。
2、使用git reset --hard id进行回退。注意,使用这个命令后,再使用git log查看id的时候,会发现只保留到你退过来的这个id,比它新的都已经没有了。如果这时候你想反悔,也就是想“往前回退”,需要使用git reflog命令查id,然后使用相同的命令就可以“往前回退”了。
3、如果不想向上面那样回退(因为id会消失),那就使用git convert --hard id来进行回退。这时候使用git log还能看到比当前版本更新的commit id
4、使用git push -f origin master来更新远端仓库中的内容。
5、如果不小心改错了,想放弃修改,可以使用git checkout -- 改错的文件名来放弃本地目录中的修改,回到你上次提交的版本。注意,如果此时你已经将错误的命令提交到暂存区,使用这个命令是无效的,你需要先使用git reset HEAD 改错的文件名来放弃暂存区中的内容,然后再使用git checkout -- 改错的文件名来放弃本地目录中的修改。

6 疑难问题

1、我有两个分支,我改了一个分支中本地目录中的文件,那另一个分支中的本地目录的文件会被修改吗?
这个需要分情况讨论。
如果你在A分支更改了本地目录中的文件,然后没有保存到暂存区就使用git checkout切换了分支,那么很抱歉另一个分支的本地目录的相应文件也被更改了。
如果你在A分支更改了本地目录中的文件,然后保存到了暂存区后想使用git checkout切换分支,那么此时会报错无法成功完成分支切换,会提示你先提交。
如果你在A分支更改了本地目录中的文件,然后保存到了暂存区,然后提交到了HEAD,然后使用git checkout切换分支,那么并不会更改你刚切换到的这个分支里的本地目录的文件。

参考资料

以下两个网站内容丰富,推荐阅读!
https://rogerdudler.github.io/git-guide/index.zh.html
https://www.cnblogs.com/zeo-to-one/p/8367801.html

linux如何将一个正在运行的进程转入到后台执行且中断shh连接不被kill掉

背景

最近在跑程序的时候,遇到一个问题就是需要先下载数据包,但是这个数据包非常大,而且网速较慢,需要很长时间。而一旦中断与服务器的连接,所有的进程就都被kill掉了。所以需要在后台运行,且不能在断开shh连接后被kill掉。

操作步骤

1、执行自己的程序。例如 python hello.py
2、按下ctrl+z暂停进程并且返回shell。
3、输入bg命令,使暂停的进程在后台运行。
4、输入jobs,记录这个进程的编号。输出内容最前面有个中括号[],里面的就是编号。
5、输入disown -h %上一步查到的编号,例如disown -h %1
此时,断开ssh连接后,进程不会被kill掉。

## 背景 创建了virtual environment,但是在sudo下却无效,提示找不到包,然而这个包其实安装过了。 ## 解决办法 直接使用venv下python的绝对路径, “` sudo 你自己的虚拟环境目录/bin/python hello.py “` 例如 “` sudo /home/wlg/venv/bin/python hello.py “`

背景

sudo下python默认是python2.7,而在自己的用户下python默认是3.6,如何将sudo下python也变成python3.6呢?

解决方法-基于update-alternatives

注:以下内容转载自https://blog.csdn.net/White_Idiot/article/details/78240298

可以使用update-alternatives来为整个系统更改Python版本。

第1步首先列出所有可用的python替代版本信息:

$ update-alternatives --list python

update-alternatives: 错误: 无 python 的候选项

如果出现以上所示的错误信息,表示update-alternatives没有添加Python的替代版本。

第2步将Python的替代版本添加进去:

$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1

update-alternatives: 使用 /usr/bin/python2.7 来在自动模式中提供 /usr/bin/python (python) 

$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.5 2

update-alternatives: 使用 /usr/bin/python3.5 来在自动模式中提供 /usr/bin/python (python)

install选项使用了多个参数用于创建符号链接。最后一个参数指定了此选项的优先级,如果我们没有手动来设置替代选项,那么具有最高优先级的选项就会被选中。

这个例子中,我们为/usr/bin/python3.5设置的优先级为2,所以update-alternatives命令会自动将它设置为默认Python版本:

$ python --version

Python 3.5.2

再列出可用的Python替代版本:

$ update-alternatives --list python

/usr/bin/python2.7
/usr/bin/python3.5

现在就可以在列出的Python替代版本中任意切换:

$ update-alternatives --config python

有 2 个候选项可用于替换 python (提供 /usr/bin/python)。

  选择       路径              优先级  状态
------------------------------------------------------------
* 0            /usr/bin/python3.5   2         自动模式
  1            /usr/bin/python2.7   1         手动模式
  2            /usr/bin/python3.5   2         手动模式

要维持当前值[*]请按<回车键>,或者键入选择的编号:1

然后查看版本号:

$ python --version

Python 2.7.12
第3步当系统不再存在某个Python替代版本时,我们可以将其从update-alternatives列表中删除掉。

例如,可以将列表中的python2.7版本移除:

$ sudo update-alternatives --remove python /usr/bin/python2.7 

$ update-alternatives --list python
/usr/bin/python3.5

【Java题解】剑指 Offer 12. 矩阵中的路径

一、题目

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。

[["a","b","c","e"], ["s","f","c","s"], ["a","d","e","e"]]

但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

 

示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]],
word = "ABCCED"
输出:true

示例 2:
输入:board = [["a","b"],["c","d"]], word = "abcd"  
输出:false
提示:

1 <= board.length <= 200
1 <= board[i].length <= 200

二、代码

class Solution {

    private int rowl, coll;
    private boolean[][] visited;
    private int[][] direction;

    public boolean exist(char[][] board, String word) {
        if(board == null || word == null || board.length == 0 || board[0].length == 0){
            return false;
        }
        rowl = board.length;
        coll = board[0].length;
        visited = new boolean[rowl][coll];
        direction = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
        char[] mywords = word.toCharArray();
        for(int i = 0; i &lt; rowl; i++){
            for(int j = 0; j &lt; coll; j++){
                visited[i][j] = false;
            }
        }
        for(int row = 0; row &lt; rowl; row++){
            for(int col = 0; col &lt; coll; col++){
                boolean res = dfs(board, mywords, row, col, 0);
                if(res){
                    return true;
                }
            }
        }
        return false;
    }

    public boolean dfs(char[][] board, char[] mywords, int row, int col, int index){
        if(visited[row][col] || board[row][col] != mywords[index]){
            return false;
        }
        if(index == mywords.length - 1){
            return true;
        }
        visited[row][col] = true;
        boolean result = false;
        for(int[] dir : direction){
            int newr = row + dir[0];
            int newc = col + dir[1];
            if(newr &gt;= 0 &amp;&amp; newr &lt; rowl &amp;&amp; newc &gt;= 0 &amp;&amp; newc &lt;coll &amp;&amp; !visited[newr][newc]){
                boolean res2 = dfs(board, mywords, newr, newc, index+1);
                if(res2){
                    return true;
                }
            }
        }
        visited[row][col] = false;
        return false;
    }
}