git与repo与scp

  • Ubuntu下git的安装与使用
    • 安装
    • 使用
    • git生成patch和打patch
      • 生成patch
      • 应用patch
      • 打patch发生冲突
    • git分支
      • 这些是各种场合常见的 Git 命令:
  • repo
    • 概要
    • 工作原理
      • 项目清单库(.repo/manifests)
      • repo脚本库(.repo/repo)
      • 仓库目录和工作目录
    • 使用repo
      • help
      • init
        • init错误
      • sync
      • upload
      • download
      • forall
      • prune
      • start
      • status
      • repo update[ project-list ]
      • repo diff [ project-list ]
      • repo download target revision
      • repo start newbranchname
      • Repo干了些什么?
  • Ubuntu 安装和卸载软件的一般方法:
    • 安装软件
    • 卸载软件
  • scp

Ubuntu下git的安装与使用

Git是一个分布式版本控制程序,您可以在开发软件时使用它监视代码的变化(版本)。 Git提供了恢复到前一阶段,多个工作流程,邻居分支以及其他许多功能的功能。 这使Git成为最好的版本控制系统之一,这也是许多软件开发人员使用Git的原因。
git如何卸载:

  • 找到git的位置
    终端命令:which -a git
    cd进入git所在的目录
    终端命令:cd /usr/bin/git(这个是一般的默认位置)
    删除命令
    终端命令:sudo rm -rf git*
  • 为了确保完全卸载可以使用:sudo apt-get remove git。

安装

  • 首先,通过运行以下命令确保您的系统和apt包列表完全更新
 sudo apt-get update
  • 确认你的系统是否已安装git,可以通过git指令进行查看,如果没有,在命令行模式下输入sudo apt-get install git命令进行安装。使用git --version确认git版本
  • 在Git中配置自己的名称和电子邮件地址,以便您提交的更改包含正确的信息。进行git配置,输入指令git config --global user.name "xxx"git config --global user.email "你的邮箱地址"。接下来,我们将通过查看.gitconfig来验证配置更改: git config --list或者git config -lgit config user.name查看用户名,git config user.email查看电子邮箱。注意git config命令的–global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
  • 配置完成后,需要创建验证用的公钥,因为git是通过ssh的方式访问资源库的,所以需要在本地创建验证用的文件。使用命令ssh-keygen -C '你的邮箱地址' -t rsa(注意ssh与-keygen之间没有空格),会在用户目录~/.ssh/下建立相应的密钥文件(可以拷贝其他人的.shh)。
  • 创建完公钥后,需要上传。使用命令cd ~/.ssh,进入.ssh文件夹,输入gedit id_rsa.pub打开id_rsa.pub文件,复制其中所有内容。接着访问相关网页,点击SSH公钥,标题栏可以随意输入,公钥栏把你刚才复制的内容粘贴进去就OK了。

使用

git init在想要创建为仓库的文件夹中使用
git init dirname或者直接在当前文件夹中创建一个文件夹并初始化为仓库
git status查看当前仓库文件的状态。
git add xxx命令把xxx文件加入到暂存区。再使用git commit -m "注释内容"把xxx从暂存区提交到版本库。git commit --amend修改最近一次的commit 信息,进入vim编辑模式,修改最近一次的commit信息.
git commit -a在 commit 的时候,能帮你省一步 git add ,但也只是对修改和删除文件有效, 新文件还是要 git add,不然就是 untracked 状态。
我们想看一下xxx到底改了什么内容,可以使用git diff xxx
使用命令git log查看历史版本记录,git log --graph会显示分支线。
可以按照每一次版本变更为一行内容进行显示,使用命令git log --pretty=oneline或者git log --oneline
git push origin HEAD:refs/for/master push到master分支上

回退版本:
git reset --hard HEAD^回到上一个版本,git reset --hard HEAD^^回退到上上一个版本,以此类推;
② 如果回退到前50个版本的话,使用方法①就显得不太明智了,我们可以使用简便命令操作:git reset --hard HEAD~50就可以了。git reset --hard HEAD~0拉最新版本。
回退版本之后通过git reflog来查看比当前新的版本。通过git reset --hard 版本号到达指定版本号。
**撤销修改和删除文件:**在写代码的时候发现我新增加的内容有问题,我必须马上恢复以前的版本,现在可以采取的操作有:
① 如果知道要删掉的内容,直接可以手动去改掉,然后重新add并commit即可。
② 也可以按照前面版本回退的方法直接恢复到上一个版本。git reset --hard HEAD^
③使用git checkout -- xxx可以丢弃工作区的修改。
在删除了一个文件没有commit是使用git checkout -- xxx从版本库中恢复.

撤回提交:
Git有三大区(工作区、暂存区、版本库)以及几个状态(untracked、unstaged、uncommited),Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照。

  1. 第一种情况:还没有push,只是在本地commit
git reset --soft|--mixed|--hard <commit_id>  (这里的<commit_id>就是每次commit的SHA-1,可以在git log里查看到)
git push develop develop --force  (本地分支和远程分支都是 develop)

–mixed 修改本地仓库、暂存区里面的数据为commitId对应快照里的数据,是git reset默认的参数,–mixed可缺省。 暂存区的数据会被快照中的数据覆盖
–soft 修改本地仓库里面的数据为commitId对应快照的数据。(仅改变指向快照的指针指向)
–hard 修改本地仓库、暂存区、工作区里面的数据为commitId对应快照的内数据
当push代码以后,又用 reset --hard <commit…> 回退代码到某个版本之前,但是这样会有一个问题,你线上的代码没有变,线上commit,index都没有变,当你把本地代码修改完提交的时候你会发现全是冲突…这时换下一种。

  1. commit push 代码已经更新到远程仓库
    git reset --hard HEAD^直接删除上次提交,或者
    git revert [--no-commit] <commit> 可以撤销指定的提交, 要撤销一串提交可以用 <commit1>..<commit2> 语法。
    注意这是一个前开后闭区间,即不包括 commit1,但包括 commit2。
    注意 revert 命令会对每个撤销的 commit 进行一次提交,--no-commit 后可以最后一起手动提交。
    注意:git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit,看似达到的效果是一样的,其实完全不同。
    区别:
    第一:上面我们说的如果你已经push到线上代码库,reset 删除指定commit以后,你git push可能导致一大堆冲突,但是revert 并不会。
    第二:如果在日后现有分支和历史分支需要合并的时候,reset 恢复部分的代码依然会出现在历史分支里。但是revert 方向提交的commit 并不会出现在历史分支里。
    第三:reset 是在正常的commit历史中,删除了指定的commit,这时 HEAD 是向后移动了,而 revert 是在正常的commit历史中再commit一次,只不过是反向提交,他的 HEAD 是一直向前的。

git revert -n 版本号反做该版本号的版本,再commit提交。最后都可以用diff确认。

修改上次提交:
git commit --amend用来修改最后一条提交的 commit message, 也可以追加新的修改.
amend 了错误的内容, 如何回退呢?
一般会用 git reset 撤销到上一个提交, 再重新git commit一次, 这固然是可以的. 但如果工作区此时已经改的面目全非, 这时如果执行 git reset, 就很难分的清哪些内容属于被撤销的提交了. 嗯, 这位同学说这种情况可以用 git stash 来处理, 是可以解决问题的.
如果只 amend 了一次, 那么直接用 git reset HEAD@{1} 就可以撤销这次 amend. 如果 amend 多次, 就使用 git reflog查看历史记录,然后选择指定的地方(x)进行撤销git reset HEAD@{x}.
如果想撤销到暂存区, 就用 git reset --soft HEAD@{1} .
如果想干掉这个修改, 就用 git reset --hard HEAD@{1} .

git生成patch和打patch

生成patch

git diff xxx.java > xxx.patch  #只想 patch xxx.java 文件
git diff > xxx.patch  #把所有的修改文件打成 patch
git format-patch HEAD^       #生成最近的1次commit的patch(HEAD^^以此类推)
git format-patch <r1>..<r2>  #生成两个commit间的修改的patch(包含两个commit. <r1>和<r2>都是具体的commit号)
git format-patch -1 <r1>     #生成单个commit的patch
git format-patch <r1>        #生成r1以来的修改patch(不包含该commit)
git format-patch --root <r1> #生成从根到r1提交的所有patch

应用patch

  • git am会直接将patch的所有信息打上去,而且不用重新git add和git
    commit,需要自己push。 git am xxx.patch
  • git apply是另外一种打patch的命令,其与git
    am的区别是:git apply并不会将commit message等打上去,打完patch后需要重新git add和git
    commit,然后再push。 git apply xxx.patch
git am 0001-limit-log-function.patch           # 将名字为0001-limit-log-function.patch的patch打上
git am --signoff 0001-limit-log-function.patch # 添加-s或者--signoff,还可以把自己的名字添加为signed off by信息,作用是注明打patch的人是谁,因为有时打patch的人并不是patch的作者
git am ~/patch-set/*.patch                     # 将路径~/patch-set/*.patch 按照先后顺序打上
git am --abort                                 # 当git am失败时,用以将已经在am过程中打上的patch废弃掉(比如有三个patch,打到第三个patch时有冲突,那么这条命令会把打上的前两个patch丢弃掉,返回没有打patch的状态)
git am --resolved                              # 当git am失败,解决完冲突后,这条命令会接着打patch

检查patch的情况

git apply --stat 0001-limit-log-function.patch  # 查看patch的情况
git apply --check 0001-limit-log-function.patch # 检查patch是否能够打上,如果没有任何输出,则说明无冲突,可以打上

打patch发生冲突

解决patch冲突的过程是:如果不想打这一系列patch了,直接:git am --abort。如果还想打, 有两种解决方案:
方案一(个人推荐):

  • 根据git am失败的信息,找到发生冲突的具体patch文件,然后用命令git apply --reject
    <patch_name>,强行打这个patch,发生冲突的部分会保存为.rej文件(例如发生冲突的文件是a.txt,那么运行完这个命令后,发生conflict的部分会保存为a.txt.rej),未发生冲突的部分会成功打上patch
  • 根据.rej文件,通过编辑该patch文件的方式解决冲突
  • 废弃上一条am命令已经打了的patch:git am --abort
  • 重新打patch:git am ~/patch-set/*.patchpatch

方案二:

  • 根据git am失败的信息,找到发生冲突的具体patch文件,然后用命令git apply --reject
    <patch_name>,强行打这个patch,发生冲突的部分会保存为.rej文件(例如发生冲突的文件是a.txt,那么运行完这个命令后,发生conflict的部分会保存为a.txt.rej),未发生冲突的部分会成功打上patch
  • 根据.rej文件,通过编辑发生冲突的code文件的方式解决冲突
  • 将该patch涉及到的所有文件(不仅仅是发生冲突的文件)通过命令git add <file_name>添加到工作区中
  • 告诉git冲突已经解决,继续打patch: git am --resolved (git am --resolved 和 git am --continue是一样的)

分析:方案一和方案二主要区别是解决冲突的方法不一样。方案一是通过编辑patch文件的方式解决冲突,方案二是通过编辑冲突code文件的方式解决冲突。这两种方案区别比较大:经过实验,核心区别在于,方案二无法验证冲突有没有切实的解决。即使你在方案二的第二步乱改一通,也能“打完”发生冲突的patch(并没有检测修改后的code文件跟patch期望的是否相同)。因此,如果采用方案二,那么再解决code文件冲突后,需要人工去确认修改的正确性。

patch就是打补丁,通过git工具把代码的差分,生成patch文件,然后通过git工具可以直接把patch文件的内容,merge到代码里面。
生成patch的命令

    git diff > patch //本地变更 git diff 的内容,生成patch文件git diff branchname --cached > patch //branch 之间差分生成patch文件git diff commit-id-new commit-id-old --name-only|xargs tar cjvf xxxxx-patch.tar.bz2 可以根据提交按照目录树快速生成补丁文件.git format-patch HEAD^ //最近一次提交节点的patchgit format-patch 节点A 节点B //两个节点之间的patch

使用patch

        git apply patch //将patch文件内容差分到本地,在使用patch之前可以使用以下命令,来测试,是否可以将patch完美打入本地srcgit apply --check patch

git分支


git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。
git fetch <远程主机名> 这个命令将某个远程主机的更新全部取回本地
git fetch <远程主机名> <分支名> 注意之间有空格,只想取回特定分支的更新
git push -f强行push
git pull 则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决。
git pull <远程主机名> <远程分支名>:<本地分支名>将远程主机的某个分支的更新取回,并与本地指定的分支合并。如果远程分支是与当前分支合并,则冒号及后面的部分可以省略。
git cherry-pick <分支名> 能够把另一个分支的一个或多个提交复制到当前分支。
git commit --amend重新提交(提交后本地更新了再次提交但是是上次的提交,新的commit替换了原来的commit,是在日志看不到操作记录的),等价于:

git reset --soft HEAD^  //将branch的头指针向前移动一个commit,--soft选项使得index和workspace tree的内容保持移动之前不变
...do something...
git commit -c ORIG_HEAD  //-c选项使得新提交的log message重用ORIG_HEAD指向的commit使用的log message,但允许用户编辑

每次提交,Git都把它们串成一条时间线,这条时间线是一个分支。
1.查看所有分支命令git branch。git branch查看分支,会列出所有分支,当前分支前面有一个星号。更多git branch [-*]
2.git checkout -b 分支名 创建并切换到这个分支。
git checkout命令加上参数-b就代表创建之后切换到,相当于两条命令:git branch 分支名git checkout 分支名 。通常我们合并分支的时候,
分支策略:master主分支应该是非常稳定的,也是用来发布的新版本,一般情况下干活都不在master分支上干,都是在新建的分支上,干完之后需要发布,或者说新建分支代码稳定之后可以合并到主分支master上。
3.想把xxx1分支上增加的内容合并到分支xxx2分支上,可以在xxx2分支上使用如下命令:git merge 分支名。Git一般是用Fast forward模式,这种模式下,删除分支之后,会丢掉分支信息,现在我们来使用git merge --no-ff -m "注释内容" 分支名来禁用Fast forward模式。删除分支之后发现在最后的git log中还有删除的分支的操作。但是git branch没有了删除的分支。
4.git branch -d xxx删除分支。
5.在xxx1分支上我们修改提交了新内容,在xxx2上也修改提交了新内容,合并的时候在xxx2分支上进行合并xxx1分支,会有冲突,并且分支名也从xxx2变成了xxx2 | MERGING, 同时我们cat 冲突文件发现文件内容也变了,在git status上给我们提供了解决方法:git commit
Git使用了

<<<<<<<  HEAD
XXX1分支的冲突的内容
========
XXX2分支的冲突的内容
>>>>>>> xxx1

分别标记出不同分支修改的内容,我们可以打开文件修改成和主分支一致,然后在xxx2 | MERGING这个临时分支上进行git commit。
6.bug分支
在开发过程中,bug问题是不能避免的,那么有了bug就需要修复,在Git中,由于拥有强大的分支,每个bug我们都可以通过一个临时分支来修复,修复完成之后合并分支,然后将临时的分支删除掉。
例如我在开发中接到一个404bug的时候,可以临时创建一个404分支来修复。但是我目前在的分支xxx1的开发工作还没有完成,但是bug需要五个小时内完成,怎么办?这时候Git有一个git stash功能,可以将当前工作现场隐藏到后台,等以后再恢复现场继续工作。接下来我们要知道bug是哪个分支上的,比如bug是master分支上的,我就需要再master分支上重新建一个分支git checkout -b 404,处理好后add commit,再切换到master分支git checkout master,并合并git merge --no-ff -m "修复了404" 404,最后删除这个临时分支git branch -d 404。现在又可以回到当前的分支上继续干活了。要把我们的现场恢复回来:通过git stash list查看隐藏的工作现场,恢复的方式有两种:
1.git stash apply,这种恢复方式恢复后stash内容并不删除,需要使用git stash drop来删除。
2.另一种方式是使用git stash pop,恢复的同时把stash内容也删除了。
7.多人合作

①当我们从远程库克隆的时候,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且远程库的默认名称是origin。
1.查看远程信息git remote
2.查看远程库详细信息git remote -v
②推送分支
推送一个分支就是把该分支上所有本地提交到远程库上,推送的时候要制定本地的分支,Git会把该分支推送到远程库对应的远程分支上:使用命令git push origin master。需要推送哪个分支我们就把参数换成分支名就可以了。一般情况下master分支是主分支,因此要时时刻刻与远程同步;一些修复的bug分支是不需要推送到远程的,只要先在本地合并到主分支上,然后把主分支master推送到远程去即可。
③抓取分支
在进行多人协作时,大家都会往master分支上推送各自的修改,现在我们假设有另外一个同事,这个同事需要在xxx2分支上做开发,在终端用命令创建一个xxx2分支,在xxx2分支上进行开发,开发完成后,把xxx2分支推送到远程库中。然后我也修改了一下把分支xxx2push到远程上,然后push失败,推送失败的原因是同事最近也提交了,提交到有冲突,提示我们,先用git pull把最新的提交抓取下来,然后在本地合并,解决冲突之后再推送。
先要指定本地xxx2分支与远程xxx2分支的连接,根据提示设置xxx2分支和xxx2的链接,再本地分支git branch --set-upstream xxx2 xxx2,然后git pull,就看到了熟悉的MERGING临时分支了;解决方式和之前是一样的,先看一下内容,然后修改,然后再继续推送到远程中。
所以:多人协作的工作模式是:
1可以试图用git push origin branch name推送自己的修改
2如果推送失败,是因为远程分支比本地更新早,需要先用git pull试图合并。
3如果合并有冲突,需要解决冲突,并在本地提交,使用git push origin branch name

这些是各种场合常见的 Git 命令:

开始一个工作区(参见:git help tutorial)
clone 克隆一个仓库到一个新目录
init 创建一个空的 Git 仓库或重新初始化一个已存在的仓库

在当前变更上工作(参见:git help everyday)
add 添加文件内容至索引
mv 移动或重命名一个文件、目录或符号链接
reset 重置当前 HEAD 到指定状态
rm 从工作区和索引中删除文件

检查历史和状态(参见:git help revisions)
bisect 通过二分查找定位引入 bug 的提交
grep 输出和模式匹配的行
log 显示提交日志
show 显示各种类型的对象
status 显示工作区状态

扩展、标记和调校您的历史记录
branch 列出、创建或删除分支
checkout 切换分支或恢复工作区文件
commit 记录变更到仓库
diff 显示提交之间、提交和工作区之间等的差异
merge 合并两个或更多开发历史
rebase 在另一个分支上重新应用提交
tag 创建、列出、删除或校验一个 GPG 签名的标签对象

协同(参见:git help workflows)
fetch 从另外一个仓库下载对象和引用
pull 获取并整合另外的仓库或一个本地分支
push 更新远程引用和相关的对象

命令 ‘git help -a’ 和 ‘git help -g’ 显示可用的子命令和一些概念帮助。
查看 ‘git help <命令>’ 或 ‘git help <概念>’ 以获取给定子命令或概念的帮助。

repo

概要

1、repo是什么?
官方的定义:Repo是谷歌用Python脚本写的调用git的一个脚本,可以实现管理多个git库。repo的出现,并非为了取代git,而是为了让Android开发者更为有效的利用git。
个人理解:repo这个工具,是一个脚本。这个脚本是对git库的管理。
类似什么呢,类似makfile。功能是使你简单一敲make,就ok了。repo 呢,简单一敲,repo init -u 。url 指的是 manifest仓库地址,option 一般是所在分支,比如-b 你的分支,就行了。再执行一句,repo sync 。刷刷刷,等待个几十个小 时,(网速好的,时间相对短一点)。就把你需要的安卓整个源码同步在本地了(几百个G)。
值得提一下的是,为什么有repo这个功能。
repo呢,其实来说,就是很多个git clone 的集成,如果有一个工程,有一百个git,你下载下来,按逻辑是敲一百次git clone xxxx,下载下来。但是使用repo呢,只需要敲一次,喝喝茶,等待下载完成就可以了。
Android源码包含数百个git库,仅仅是下载这么多git库就是一项繁重的任务,所以在下载源码时,Android就引入了repo。 Android官方推荐下载repo的方法是通过Linux curl命令,下载完后,为repo脚本添加可执行权限:

mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/    git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
*************新UBuntu20.04
mkdir -p ~/.bin
PATH="${HOME}/.bin:${PATH}"
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
chmod a+rx ~/.bin/repo

由于国内Google访问受限,所以上述命令不一定能下载成功。其实,我们现在可以从很多第三方渠道找到repo脚本,只需要取下来,确保repo可以正确执行即可。
假如repo init失败,原因是repo init会访问https://gerrit.googlesource.com/git-repo
所以我们需要将~bin/repo里面的REPO_URL 改成自己需要的URL;
这个网址就是在repo文件中定义的。
如果repo无法修改,因为它的初始状态是只读的,我们需要修改一下读写权限:

chmod 777 repo

(按情况操作:如果后续repo sync时出现问题,可以修改~/.gitconfig,或者拷贝)

工作原理

repo需要关注当前git库的数量、名称、路径等,有了这些基本信息,才能对这些git库进行操作。通过集中维护所有git库的清单,repo可以方便的从清单中获取git库的信息。 这份清单会随着版本演进升级而产生变化,同时也有一些本地的修改定制需求,所以,repo是通过一个git库来管理项目的清单文件的,这个git库名字叫manifests。

当打开repo这个可执行的python脚本后,发现代码量并不大(不超过1000行),难道仅这一个脚本就完成了AOSP数百个git库的管理吗?并非如此。 repo是一系列脚本的集合,这些脚本也是通过git库来维护的,这个git库名字叫repo。

在客户端使用repo初始化一个项目时,就会从远程把manifests和repo这两个git库拷贝到本地,但这对于Android开发人员来说,又是近乎无形的(一般通过文件管理器,是无法看到这两个git库的)。 repo将自动化的管理信息都隐藏根目录的.repo子目录中。

项目清单库(.repo/manifests)

AOSP项目清单git库下,只有一个文件default.xml,是一个标准的XML,描述了当前repo管理的所有信息。 AOSP的default.xml的文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote  name="aosp" fetch=".." review="https://android-review.googlesource.com/" />
<default revision="master" remote="aosp" sync-j="4" />
<project path="build" name="platform/build" groups="pdk,tradefed" >
<copyfile src="core/root.mk" dest="Makefile" />
</project>
<project path="abi/cpp" name="platform/abi/cpp" groups="pdk" />
<project path="art" name="platform/art" groups="pdk" />...
<project path="tools/studio/translation" name="platform/tools/studio/translation" groups="notdefault,tools" />
<project path="tools/swt" name="platform/tools/swt" groups="notdefault,tools" />
</manifest>

<manifest>:最顶层的XML元素
<remote>:设置远程git服务器的属性,包括下面的属性: (一个manifest文件中能够配置多个remote元素,用于配置不一样的project默认下载指向。)

  • name: 在每一个.git/config文件的remote项中用到这个name,即表示每个git的远程服务器的名字(这个名字很关键,如果多个remote属性的话,default属性中需要指定default remote)。git pull、get fetch的时候会用到这个remote name。通常我们看到的命名是origin
  • alias: 远程git服务器的别名,若是指定了,则会覆盖name的设定。在一个manifest中, name不能重名,但alias能够重名。
  • fetch: 全部projects的git URL 前缀,所有git 的project name加上这个前缀,就是git url的真正路径
  • review: 指定Gerrit的服务器名,用于repo upload操做。若是没有指定,则repo upload没有效果。

<default>:设定全部projects的默认属性值,若是在project元素里没有指定一个属性,则使用default元素的属性值。在标签中,也可以重写这些属性

  • remote: 以前定义的某一个remote元素中name属性值,用于指定使用哪个远程git服务器。
  • revision: 所有git的默认branch,后面project没有特殊指出revision的话,就用这个branch,例如master或者refs/heads/master
  • sync_j: 在repo sync中默认并行的数目。
  • sync_c: 若是设置为true,则只同步指定的分支(revision 属性指定),而不是全部的ref内容。
  • sync_s: 若是设置为true,则会同步git的子项目

<project>:指定一个须要clone的git仓库。

  • name: git 的名称,用于生成git仓库的URL。URL格式:${remote_fetch}/${project_name}.git
  • path: 可选的路径。指定git clone出来的代码存放在本地的目录。若是没有指定,则以name做为目录。
  • remote: 指定以前在某个remote元素中的name。
  • revision: 指定须要获取的git提交点,能够是master, refs/heads/master, tag或者SHA-1值。若是不设置的话,默认下载当前project,当前分支上的最新代码。
  • groups: 列出project所属的组,以空格或者逗号分隔多个组名。全部的project都自动属于"all"组。每个project自动属于name:‘name’ 和path:'path’组。例如<project name=“monkeys” path=“barrel-of”/>,它自动属于default, name:monkeys, and path:barrel-of组。若是一个project属于notdefault组,则,repo sync时不会下载。
  • sync_c: 若是设置为true,则只同步指定的分支(revision 属性指定),而不是全部的ref内容。
  • sync_s: 若是设置为true,则会同步git的子项目。
  • upstream: 在哪一个git分支能够找到一个SHA1。用于同步revision锁定的manifest(-c 模式)。该模式能够避免同步整个ref空间。
  • annotation: 能够有多个annotation,格式为name-value pair。在repo forall 命令中这些值会导入到环境变量中。

如果需要新增或替换一些git库,可以通过修改default.xml来实现,repo会根据配置信息,自动化管理。但直接对default.xml的定制,可能会导致下一次更新项目清单时,与远程default.xml发生冲突。 因此,repo提供了一个种更为灵活的定制方式local_manifests:所有的定制是遵循default.xml规范的,文件名可以自定义,譬如local_manifest.xml, another_local_manifest.xml等, 将定制的XML放在新建的.repo/local_manifests子目录即可。repo会遍历.repo/local_manifests目录下的所有*.xml文件,最终与default.xml合并成一个总的项目清单文件manifest.xml。

local_manifests的修改示例如下:

$ ls .repo/local_manifests
local_manifest.xml
another_local_manifest.xml
$ cat .repo/local_manifests/local_manifest.xml
<?xml version="1.0" encoding="UTF-8"?>
<manifest><project path="manifest" name="tools/manifest" /><project path="platform-manifest" name="platform/manifest" />
</manifest>

repo脚本库(.repo/repo)

repo对git命令进行了封装,提供了一套repo的命令集(包括init, sync等),所有repo管理的自动化实现也都包含在这个git库中。 在第一次初始化的时候,repo会从远程把这个git库下载到本地。

仓库目录和工作目录

仓库目录保存的是历史信息和修改记录,工作目录保存的是当前版本的信息。一般来说,一个项目的Git仓库目录(默认为.git目录)是位于工作目录下面的,但是Git支持将一个项目的Git仓库目录和工作目录分开来存放。 对于repo管理而言,既有分开存放,也有位于工作目录存放的:
manifests: 仓库目录有两份拷贝,一份位于工作目录(.repo/manifests)的.git目录下,另一份独立存放于.repo/manifests.git。
repo:仓库目录位于工作目录(.repo/repo)的.git目录下
project:所有被管理git库的仓库目录都是分开存放的,位于.repo/projects目录下。同时,也会保留工作目录的.git,但里面所有的文件都是到.repo的链接。这样,即做到了分开存放,也兼容了在工作目录下的所有git命令。

既然.repo目录下保存了项目的所有信息,所有要拷贝一个项目时,只是需要拷贝这个目录就可以了。repo支持从本地已有的.repo中恢复原有的项目。

使用repo

repo命令的使用格式如下所示:

$ repo <COMMAND> <OPTIONS>

可选的的有:help、init、sync、upload、diff、download、forall、prune、start、status,每一个命令都有实际的使用场景, 下面我们先对这些命令做一个简要的介绍:

help

repo help [ command ] //显示command 的详细的帮助信息内容
示例: repo help init 来获取 repo init 的其他用法

16:11:30[~/t-qssi]~$  repo help
usage: repo COMMAND [ARGS]
The most commonly used repo commands are: 最常用的 repo 命令有:abandon        Permanently abandon a development branch 永久放弃开发分支branch         View current topic branches 查看当前主题分支branches       View current topic branches 查看当前主题分支checkout       Checkout a branch for development 签出一个分支进行开发cherry-pick    Cherry-pick a change. diff           Show changes between commit and working tree 显示提交和工作树之间的变化diffmanifests  Manifest diff utility 清单差异实用程序download       Download and checkout a change 下载并签出更改grep           Print lines matching a pattern 打印与图案匹配的线条info           Get info on the manifest branch, current branch or unmerged br> 获取有关清单分支、当前分支或未合并的信息init           Initialize repo in the current directory 在当前目录初始化repolist           List projects and their associated directories 列出项目及其相关目录overview       Display overview of unmerged project branches 显示未合并项目分支的概览prune          Prune (delete) already merged topics 修剪(删除)已经合并的主题rebase         Rebase local branches on upstream branch 在上游分支上重新定位本地分支smartsync      Update working tree to the latest known good revision 将工作树更新到最新的已知良好版本stage          Stage file(s) for commit 提交阶段文件start          Start a new branch for development 开始一个新的分支进行开发status         Show the working tree status 显示工作树状态sync           Update working tree to the latest revision   更新工作树到最新版本upload         Upload changes for code review   同步更新工作树到最新版本
See 'repo help <command>' for more information on a specific command.  有关特定命令的更多信息,请参阅“repo help <command>”。
See 'repo help --all' for a complete list of recognized commands. 有关已识别命令的完整列表,请参阅“repo help --all”。

init

$ repo init -u <URL> [<OPTIONS>]
例如$ repo init -u git://android.git.kernel.org/platform/manifest.git --mirror
  • -u:指定manifests这个远程git库的URL,manifests库是整个项目的清单。默认情况,这个git库只包含了default.xml一个文件,其内容可以参见Android的样本。
    示例:repo init -u git://android.git.kernel.org/platform/manifest.git
  • -m,–manifest-name:指定所需要的manifests库中的清单文件。默认情况下,会使用maniftests/default.xml
    示例:repo init -u git://android.git.kernel.org/platform/manifest.git -m dalvik-plus.xml
  • -b,–manifest-branch:指定manifest.xml文件中的一个版本,,也就是俗称的“分支”
    运行该命令后,会在当前目录下新建一个.repo子目录。
    示例:repo init -u git://android.git.kernel.org/platform/manifest.git -b release-1.0
  • 使用 –morror 则下一步和源同步的时候,本地按照源的版本库组织方式进行组织,否则会按照 manifest.xml
    指定的方式重新组织并检出到本地
.repo
├── manifests       # 一个git库,包含default.xml文件,用于描述repo所管理的git库的信息
├── manifests.git   # manifest这个git库的实体,manifest/.git目录下的所有文件都会链接到该目录
├── manifest.xml    # manifests/default.xml的一个软链接
└── repo            # 一个git库,包含repo运行的所有脚本

这些本地的目录是如何生成的呢?执行repo命令时,可以通过–trace参数,来看实际发生了什么。

$ repo --trace init -u $URL -b $BRANCH -m $MANIFEST--------------------mkdir .repo; cd .repogit clone --bare $URL manifests.gitgit clone https://android.googlesource.com/tools/repomkdir -p manifests/.git; cd manifests/.gitfor i in ../../manifests.git/*; do ln -s $ı .; donecd ..git checkout $BRANCH -- .cd ..ln -s manifests/$MANIFEST manifest.xml

首先,在当前目录下创建.repo子目录,后续所有的操作都在.repo子目录下完成;

然后,clone了两个git库,其中一个是-u参数指定的manifests,本地git库的名称是manifest.git;另一个是默认的repo,后面我们会看到这个URL也可以通过参数来指定;

接着,创建了manifest/.git目录,里面的所有文件都是到manifests.git这个目录的链接,这个是为了方便对manifests目录执行git命令,紧接着,就会将manifest切换到-b参数指定的分支;

最后,在.repo目录下,创建了一个软链接,链接到-m参数制定的清单文件,默认情况是manifests/default.xml。

这样,就完成了一个多git库的初始化,之后,就可以执行其他的repo命令了。

我们还介绍几个不常用的参数,在国内下载Android源码时,会用到:

  • –repo-url:指定远程repo库的URL,默认情况是https://android.googlesource.com/tools/repo,但国内访问Google受限,会导致这个库无法下载,从而导致repo init失败,所以可以通过该参数指定一个访问不受限的repo地址
  • –repo-branch:同manifest这个git库一样,repo这个git库也是有版本差异的,可以通过该参数来指定下载repo这个远程git库的特定分支
  • –no-repo-verify:在下载repo库时,会对repo的源码进行检查。通过–repo-url指定第三方repo库时,可能会导致检查不通过,所以可以配套使用该参数,强制不进行检查

init错误

  1. gpg: 签名建立于 xxxCST
    gpg: 使用 xxx
    gpg: 无法检查签名:没有公钥

    原因是所使用的repo命令程序发生了变化,造成变化前后两个repo的版本信息不一致
    解决办法:
    cd ~ 进入到家目录。
    rm .repoconfig/ -rf 删除配置文件(可以拷贝其他人可以的.repoconfig)

  2. sign_and_send_pubkey: signing failed: agentrefused operation

    解决方法如下:

# eval "$(ssh-agent -s)"
# ssh-add

执行上面的命令之后如果出现如下错误

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'id_rsa.rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: id_rsa.rsa
Permission denied (publickey,keyboard-interactive).

说明私钥权限太大,解决方法为chmod 600 ~/.ssh/id_rsa

sync

$ repo sync [PROJECT_LIST]

下载远程代码,并将本地代码更新到最新,这个过程称为“同步”。如果不使用任何参数,那么会对所有repo管理的进行同步操作;也可以PROJECT_LIST参数,指定若干要同步的PROJECT。 根据本地git库代码不同,同步操作会有不同的行为:

  • 当本地的git库是第一次触发同步操作时,那么,该命令等价于git clone,会将远程git库直接拷贝到本地
  • 当本地已经触发过同步操作时,那么,该命令等价于git remote update && git rebase origin/<BRANCH><BRANCH>就是当前与本地分支所关联的远程分支
    代码合并可能会产生冲突,当冲突出现时,只需要解决完冲突,然后执行git rebase --continue即可。

当sync命令正确执行完毕后,本地代码就同远程代码保持一致了。在一些场景下,我们会用到sync命令的一些参数:

  • -j:开启多线程同步操作,这会加快sync命令的执行速度。默认情况下,使用4个线程并发进行sync
  • -c, –current-branch:只同步指定的远程分支。默认情况下,sync会同步所有的远程分支,当远程分支比较多的时候,下载的代码量就大。使用该参数,可以缩减下载时间,节省本地磁盘空间
  • -d, –detach:脱离当前的本地分支,切换到manifest.xml中设定的分支。在实际操作中,这个参数很有用,当我们第一次sync完代码后,往往会切换到dev分支进行开发。如果不带该参数使用sync,
    则会触发本地的dev分支与manifest设定的远程分支进行合并,这会很可能会导致sync失败
  • -f, –force-broken:当有git库sync失败了,不中断整个同步操作,继续同步其他的git库
  • –no-clone-bundle:在向服务器发起请求时,为了做到尽快的响应速度,会用到内容分发网络(CDN, Content Delivery Network)。同步操作也会通过CDN与就近的服务器建立连接,使用HTTP/HTTPS的 $URL/clone.bundle来初始化本地的git库,clone.bundle实际上是远程git库的镜像,通过HTTP直接下载,这会更好的利用网络带宽,加快下载速度。当服务器不能正常响应下载$URL/clone.bundle,但git又能正常工作时,可以通过该参数,配置不下载$URL/clone.bundle,而是直接通过git下载远程git库。
  • 用repo sync 在抓去 android source code 的时候,会经常出现一些错误导致 repo sync 中断,每次都要手动开始。 可以用如下的命令,来自动重复:
$?=1;while [ $? -ne 0 ] ;do  repo sync ;done

upload

$ repo upload [PROJECT_LIST]

从字面意思理解,upload就是要上传,将本地的代码上传到远程服务器。upload命令首先会找出本地分支从上一次同步操作以来发生的改动,然后会将这些改动生成Patch文件,上传至Gerrit服务器。 如果没有指定PROJECT_LIST,那么upload会找出所有git库的改动;如果某个git库有多个分支,upload会提供一个交互界面,提示选择其中若干个分支进行上传操作。

upload并不会直接将改动合并后远程的git库,而是需要先得到Reviewer批准。Reviewer查看改动内容、决定是否批准合入代码的操作,都是通过Gerrit完成。 Gerrit服务器的地址是在manifests中指定的:打开.repo/manifest.xml,这个XML TAG中的review属性值就是Review服务器的URL:

<remote name="aosp"
fetch=".."
review="https://android-review.googlesource.com/" />

Gerrit的实现机制不是本文讨论的内容,但有几个与Gerrit相关的概念,是需要代码提交人员了解的:

  • Reviewer:代码审阅人员可以是多个,是需要人为指定的。Gerrit提供网页的操作,可以填选Reviewer。当有多个git库的改动提交时,为了避免在网页上频繁的填选Reviewer这种重复劳动,
    upload提供了–re, –reviewer参数,在命令行一次性指定Reviewer
  • Commit-ID:git为了标识每个提交,引入了Commit-ID,是一个SHA-1值,针对当次提交内容的一个Checksum,可以用于验证提交内容的完整性
  • Change-ID:Gerrit针对每一个Review任务,引入了一个Change-ID,每一个提交上传到Gerrit,都会对应到一个Change-ID,
    为了区分于Commit-ID,Gerrit设定Change-ID都是以大写字母 “I” 打头的。
    Change-ID与Commit-ID并非一一对应的,每一个Commit-ID都会关联到一个Change-ID,但Change-ID可以关联到多个Commit-ID
  • Patch-Set:当前需要Review的改动内容。一个Change-ID关联多个Commit-ID,就是通过Patch-Set来表现的,当通过git commit --amend命令修正上一次的提交并上传时,Commit-ID已经发生了变化,但仍可以保持Change-ID不变,这样,在Gerrit原来的Review任务下,就会出现新的Patch-Set。修正多少次,就会出现多少个Patch-Set,可以理解,只有最后一次修正才是我们想要的结果,所以,在所有的Patch-Set中,只有最新的一个是真正有用的,能够合并的。

download

$ repo download <TARGET> <CHANGE>

upload是把改动内容提交到Gerrit,download是从Gerrit下载改动。与upload一样,download命令也是配合Gerrit使用的。
<TARGET>:指定要下载的PROJECT,譬如platform/frameworks/base, platform/packages/apps/Mms
<CHANGE>:指定要下载的改动内容。这个值不是Commit-ID,也不是Change-ID,而是一个Review任务URL的最后几位数字。 譬如,AOSP的一个Review任务https://android-review.googlesource.com/#/c/23823/,其中23823就是。

forall

$ repo forall [PROJECT_LIST] -c <COMMAND>

对指定的git库执行-c参数制定的命令序列。在管理多个git库时,这是一条非常实用的命令。PROJECT_LIST是以空格区分的,譬如:

$ repo forall frameworks/base packages/apps/Mms -c "git status"

表示对platform/frameworks/base和platform/packages/apps/Mms同时执行git status命令。 如果没有指定PROJECT_LIST,那么,会对repo管理的所有git库都同时执行命令。
该命令的还有一些其他参数:

  • -r, –regex: 通过指定一个正则表达式,只有匹配的PROJECT,才会执行指定的命令
  • -p:输出结果中,打印PROJECT的名称

prune

$ repo prune [<PROJECT_LIST>]

删除指定PROJECT中,已经合并的分支。当在开发分支上代码已经合并到主干分支后,使用该命令就可以删除这个开发分支。

随着时间的演进,开发分支会越来越多,在多人开发同一个git库,多开发分支的情况会愈发明显,假设当前git库有如下分支:

* masterdev_feature1_201501   # 已经合并到masterdev_feature2_201502   # 已经合并到masterdev_feature3_201503   # 正在开发中,还有改动记录没有合并到master

那么,针对该git库使用prune命令,会删除dev_feature1_201501和dev_feature2_201502。
定义删除无用的分支,能够提交团队的开发和管理效率。prune就是删除无用分支的”杀手锏“。

start

$ repo start <BRANCH_NAME> [<PROJECT_LIST>]

在指定的PROJECT的上,切换到<BRANCH_NAME>指定的分支。可以使用–all参数对所有的PROJECT都执行分支切换操作。 该命令实际上是对git checkout命令的封装,<BRANCH_NAME>是自定义的,它将追踪manifest中指定的分支名。

当第一次sync完代码后,可以通过start命令将git库切换到开发分支,避免在匿名分支上工作导致丢失改动内容的情况。

status

$ repo status [<PROJECT_LIST>]

status用于查看多个git库的状态。实际上,是对git status命令的封装。

repo update[ project-list ]

上传修改的代码 ,如果你本地的代码有所修改,那么在运行 repo sync 的时候,会提示你上传修改的代码,所有修改的代码分支会上传到 Gerrit (基于web 的代码review 系统), Gerrit 受到上传的代码,会转换为一个个变更,从而可以让人们来review 修改的代码。

repo diff [ project-list ]

显示提交的代码和当前工作目录代码之间的差异。

repo download target revision

下载特定的修改版本到本地, 例如: repo download pltform/frameworks/base 1241 下载修改版本为 1241 的代码

repo start newbranchname

创建新的branch分支。 “.” 代表当前工作的branch 分支。

Repo干了些什么?

实际上,得到客户使用 repo 的信息后,首先下载 repo 执行脚本开始研究。

curl http://android.git.kernel.org/repo >~/bin/repo

难道只有 600 行的 python 代码么?要是这样应该很简单的呀。可以看下来,却发现远非如此。
Shell script or python?

首先 repo 脚本使用了一个魔法:从脚本第一行的 shebang 来看应该是 shell 脚本,但是满眼却都是 python 语法,怎么回事?

 1 #!/bin/sh23 ## repo default configuration4 ##5 REPO_URL='git://android.git.kernel.org/tools/repo.git'6 REPO_REV='stable'78 # Copyright (C) 2008 Google Inc....
22 magic='--calling-python-from-/bin/sh--'
23 """exec" python -E "$0" "$@" """#$magic"
24 if __name__ == '__main__':
25   import sys
26   if sys.argv[-1] == '#%s' % magic:
27     del sys.argv[-1]
28 del magic

魔法就在第 23 行,巧妙的通过 python 三引号字串写出了一个能被 python 和 shell script 都能理解的代码,以此为界,代码由 Shell 脚本进入了 Python 的世界。
Bootstrap 和真正的 repo
通过 curl 下载的的 repo 并非完整的 repo 脚本,只是一个 bootstrap。当 repo 执行时,会负责下载完整的 repo 代码,并将控制权转移给真正的 repo。
通过 main 函数,可以看到 repo 运行的开始,就试图发现本地真正的完整的 repo 代码,以便移交控制权:

544 def main(orig_args):
545   main, dir = _FindRepo()
...
586   try:
587     os.execv(main, me)

其中 545 行的 _FindRepo() 会在当前目录开始向上递归查找 “.repo/repo/main.py”,如果找到则移交控制权(587行)。
Repo bootstrap 脚本调用 init 只完成第一阶段的初始化
Repo 的 bootstrap 脚本只支持两个命令 help 和 init,而 init 也只完成 repo 版本库克隆(即安装 repo 完整工具),之后就转移控制权。
在 Repo bootstrap 执行 init 可以提供很多参数,但实际上第一阶段初始化,只用到两个参数(而且都有默认值)

  • 参数:–repo-url=URL
    repo 工具本身的 git 库地址。缺省为:git://android.git.kernel.org/tools/repo.git
  • 参数:–repo-branch=REVISION
    使用 repo 的版本库,即 repo git 库的分支或者里程碑名称。缺省为 stable

第二阶段的 repo init
执行第二阶段的 repo init,控制权已经移交给刚刚克隆出来的 repo git 库的脚本。
Repo git 库被克隆/检出到执行 repo init 命令当前目录下的 .repo/repo 子目录中,主要的执行脚本为 .repo/repo/main.py。main.py 接着执行 repo init 命令。
Repo 的代码组织的非常好,在 .repo/repo/subcmds/ 子目录下,是各个 repo 命令的处理脚本。repo init 的第二阶段脚本正是由 .repo/repo/subcmds/init.py 负责执行的。第二阶段主要完成:

  • 克隆由 -u 参数提供的 manifest Git 库,如克隆 android 库时:$ repo init -u git://android.git.kernel.org/platform/manifest.git
  • 如果不提供 -b REVISION 或者 –manifest-branch=REVISION参数,则检出 manifest Git 库的
    master 分支
  • 如果不提供 -m NAME.xml 或者 –manifest-name=NAME.xml 参数,则使用缺省值 default.xml
  • 如果提供 –mirror 参数,则后续同步操作会有相应的体现

Repo start 干了些什么?
Android 源码网站在介绍 repo 的使用模型中,有一个图片: http://source.android.com/images/git-repo-1.png , 介绍了 repo 的使用流程。其中 “repo start” 是紧接着 “repo sync” 后的第一个动作。那么这个动作是干什么的呢?

得益于 repo 对 git 操作的封装,”repo start” 命令的处理代码只有区区 68 行。

 37   def Execute(self, opt, args):  41     nb = args[0]  47     projects = []48     if not opt.all:49       projects = args[1:]  54     all = self.GetProjects(projects)...57     for project in all:59       if not project.StartBranch(nb):60         err.append(project)

看到第 59 行了么,就是对 repo 同步下来的项目的多个 Git 版本库,逐一执行 project.StartBranch 操作。 nb 是 repo start 的第一个参数,即分支名称。

关于 StartBranch 的代码,在 project.py 中:

 857   def StartBranch(self, name):858     """Create a new branch off the manifest's revision.859     """894     if GitCommand(self,895                   ['checkout', '-b', branch.name, revid],896                   capture_stdout = True,897                   capture_stderr = True).Wait() == 0:898       branch.Save()899       return True

原来如此, repo start <branch_name> 就是逐一为各个版本库创建工作分支,以便在此分支下进行工作。

读者可以按图索骥,找到 repo 各个命令的实现,破解心中的疑惑。

Ubuntu 安装和卸载软件的一般方法:

安装软件

在ubuntu当中,安装应用程序有三种方法,分别是apt-get,dpkg安装deb两种方法,下面来看看详细的介绍吧。

  • 通过deb包安装的情况:
    安装.deb包代码:sudo dpkg -i package_file.deb
    反安装.deb包:
    代码:sudo dpkg -r package_name
  • 通过apt-get安装的情况:
    安装代码:
    sudo apt-get install package_name
    反安装代码:
    sudo apt-get remove package_name
    sudo dpkg -p package_name卸载软件包及其配置文件,但无法解决依赖关系!
    sudo aptitude purge package_name卸载软件包及其配置文件与依赖关系包!

sudo apt-get update 更新源
sudo apt-get install package 安装包
sudo apt-get remove package 删除包
sudo apt-get –purge remove package卸载一个已安装的软件包(删除配置文件)
sudo apt-cache search package 搜索软件包
sudo apt-cache show package 获取包的相关信息,如说明、大小、版本等
sudo apt-get install package --reinstall 重新安装包
sudo apt-get -f install 修复安装
sudo apt-get build-dep package 安装相关的编译环境
sudo apt-get upgrade 更新已安装的包
sudo apt-get dist-upgrade 升级系统
sudo apt-cache depends package 了解使用该包依赖那些包
sudo apt-cache rdepends package 查看该包被哪些包依赖
sudo apt-get source package 下载该包的源代码
sudo apt-get clean && sudo apt-get autoclean 清理无用的包
sudo apt-get check 检查是否有损坏的依赖

卸载软件

找到此软件,然后使用如下命令卸载,其中xxx为程序名,purge参数意为彻底删除文件。

sudo apt-get purge XXX

然后使用以下两条命令来清除残余的配置文件

sudo apt-get autoremove
sudo apt-get clean

清除所有已删除包的残馀配置文件

dpkg -l |grep ^rc|awk '{print $2}' |sudo xargs dpkg -P

如果报如下错误,证明你的系统中没有残留配置文件了,无须担心

dpkg: --purge needs at least one package name argument

scp

Linux scp 命令用于 Linux 之间复制文件和目录。
scp -p -P **** ****:hooks/commit-msg .git/hooks/复制commit-id信息

scp 是 secure copy 的缩写, scp 是 linux 系统下基于 ssh 登陆进行安全的远程文件拷贝命令。
scp 是加密的,rcp 是不加密的,scp 是 rcp 的加强版。
语法:
scp [-1246BCpqrv]

  • -1: 强制scp命令使用协议ssh1
  • -2: 强制scp命令使用协议ssh2
  • -4: 强制scp命令只使用IPv4寻址
  • -6: 强制scp命令只使用IPv6寻址
  • -B: 使用批处理模式(传输过程中不询问传输口令或短语)
  • -C: 允许压缩。(将-C标志传递给ssh,从而打开压缩功能)
  • -p:保留原文件的修改时间,访问时间和访问权限。
  • -q: 不显示传输进度条。
  • -r: 递归复制整个目录。
  • -v:详细方式显示输出。scp和ssh(1)会显示出整个过程的调试信息。这些信息用于调试连接,验证和配置问题。

[-c cipher] -c cipher: 以cipher将数据传输进行加密,这个选项将直接传递给ssh。
[-F ssh_config] -F ssh_config: 指定一个替代的ssh配置文件,此参数直接传递给ssh。
[-i identity_file]-i identity_file: 从指定文件中读取传输时使用的密钥文件,此参数直接传递给ssh。
[-l limit] -l limit: 限定用户所能使用的带宽,以Kbit/s为单位。
[-o ssh_option] -o ssh_option: 如果习惯于使用ssh_config(5)中的参数传递方式,
[-P port] -P port:注意是大写的P, port是指定数据传输用到的端口号
[-S program]-S program: 指定加密传输时所使用的程序。此程序必须能够理解ssh(1)的选项。
[[user@]host1:]file1 [...] [[user@]host2:]file2
实例

  1. 从本地复制到远程命令格式:
    scp local_file remote_username@remote_ip:remote_folder
    或者
    scp local_file remote_username@remote_ip:remote_file
    或者
    scp local_file remote_ip:remote_folder
    或者
    scp local_file remote_ip:remote_file
    第1,2个指定了用户名,命令执行后需要再输入密码,第1个仅指定了远程的目录,文件名字不变,第2个指定了文件名;
    第3,4个没有指定用户名,命令执行后需要输入用户名和密码,第3个仅指定了远程的目录,文件名字不变,第4个指定了文件名;

  2. 从远程复制到本地
    从远程复制到本地,只要将从本地复制到远程的命令的后2个参数调换顺序即可,如下实例
    应用实例:
    scp root@www.runoob.com:/home/root/others/music /home/space/music/1.mp3
    scp -r www.runoob.com:/home/root/others/ /home/space/music/

git与repo与scp相关推荐

  1. Git和Repo扫盲——如何取得Android源代码

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的分布式版本控制软件,它不同于Subversion.CVS这样的集中式版本控制系统.在集中式版本控制系统 ...

  2. Git和Repo管理使用简要介绍

    在Linux平台下进行Android系统项目开发时,需要git或repo管理. 一. Git和Repo的区别: 1. Git:Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的 ...

  3. git(5)---Git 与Repo 管理Android代码

    Git 与Repo 管理代码 要处理 Android 代码,您需要同时使用 Git 和 Repo.在大多数情况下,您可以仅使用 Git(不必使用 Repo),或结合使用 Repo 和 Git 命令以组 ...

  4. git(4)---Git、Repo、Gerrit三者的区别

    Git.Repo.Gerrit三者的区别 Git作为一个分布式版本控制工具,可以创建分支,切换分支,方便协作,git pull/push: --但是对于类似于android如此庞大的项目,只用git库 ...

  5. 解决”error: info is different in .repo/manifests/.git vs .repo/manifests.git报错

    经常碰到这样的情况:".repo/manifests/"仓库有更新,我们在手动git pull到最新后,再执行sync或者init会报"error: info is di ...

  6. 构建git+gerrit+repo的Android代码服务器

    谷歌的Android源码是基于Git+Repo管理的,官方推荐的代码管理也是git+gerrit+repo.谷歌自己都在用的东西,各种优点,各种强大就不用说了,你懂的.关于它们的介绍可查阅极客学院的W ...

  7. Git与Repo入门

    版本控制 版本控制是什么已不用在说了,就是记录我们对文件.目录或工程等的修改历史,方便查看更改历史,备份以便恢复以前的版本,多人协作... 一.原始版本控制 最原始的版本控制是纯手工的版本控制:修改文 ...

  8. android git 版本管理,Android版本管理(git 和 repo)

    看了好久android論壇上的介紹,還是不明白,沒辦法,自己測試一下吧 首先下載好源碼.... 1.作Branch分支 $ repo start BRANCH_NAME PROJECT 比如,我要做自 ...

  9. git(17)---repo的基本认识

    repo的基本认识 1.定义. Repo是谷歌用Python脚本写的调用git的一个脚本.主要是用来下载.多个Git仓库. 而Android项目那是由多个git仓库组成的,它有非常多的分支. 如:an ...

最新文章

  1. 【推荐】ZendStudio 5.5.1 开发调试(Debug)配置说明
  2. 安科 OJ 1190 连接电脑 (并查集)
  3. spring mvc+junit
  4. 201709-5 除法 ccf(树状数组)
  5. JAVA执行过程sql,SQL 执行过程
  6. 【Java从入门到头秃专栏 8】语法篇(七) :反射 动态代理 注解
  7. 微软在动态语言支持上超越了Java?
  8. Windows Phone 7 使用Canvas Grid StackPanel进行布局管理
  9. 中移4G模块-ML302-OpenCpu开发-(MQTT连接阿里云-接收和发送数据)
  10. c语言输出方框□怎么回事_值得收藏的 C语言指针讲解文章,确实不错!
  11. 设计模式之桥接模式(Java语言描述)
  12. Java 最常见的 200+ 面试题:面试必备
  13. 淘宝天猫融合能拉回“出淘”的用户吗?
  14. python html跨平台尝试Eel
  15. 微信小程序---判断苹果11及以上型号手机
  16. c语言-是不是太胖了
  17. 一篇文章彻底清楚shellcode(精品)
  18. linux美元符号切换为井号,MyBatis中井号与美元符号的区别
  19. 小程序tabBar底部如何实现?
  20. 企业2019年会颁奖典礼PPT模板

热门文章

  1. 西电计算机专业课资料汇总
  2. visual studio2019改了账户登录选项也无法登陆的解决办法
  3. BB10 读取NFC tag
  4. 毕业论文如何引用自己写的博客?
  5. ios 自动缩小字体_技巧:如何改变iPhone上的字体大小
  6. 2021年煤矿采煤机(掘进机)操作考试题及煤矿采煤机(掘进机)操作考试总结
  7. CW2015电量计驱动分析
  8. python趣味题_从CSDN的趣味题学PYTHON
  9. kdb内核调试 - 5
  10. 【文献阅读】数据挖掘技术在制冷空调行业的应用