基于 Linux 的批量上传本地 Git 仓库到 Github 的实践

发布时间:2023年12月26日

一、需求

app目录下的每个文件夹都是一个git仓库,如何使用shell脚本将所有git仓库都上传到github上

server@dev-fj-srv:~/code/app$ tree -L 1
.
|-- FreemeBadgeProvider
|-- FreemeCalculator
|-- FreemeCamera
|-- FreemeCamera2 

在这里插入图片描述

二、上传本地 Git 仓库

2.1 初始版本

要使用 shell 脚本将 app 目录下的所有 Git 仓库上传到 GitHub 上,可以按照以下步骤进行操作:

  1. 首先,确保你在 GitHub 上创建了一个空的远程仓库,用于存储你的应用程序仓库。

  2. 创建一个新的 shell 脚本文件(例如 upload_to_github.sh),并使用文本编辑器打开它。

  3. 在脚本文件中,添加以下内容:

#!/bin/bash

# 进入 app 目录
cd ~/code/app

# 遍历 app 目录下的每个文件夹
for repo in */; do
  # 进入每个 Git 仓库目录
  cd "$repo"

  # 添加远程仓库地址
  git remote add origin <GitHub 仓库的 URL>

  # 推送代码到远程仓库
  git push -u origin master

  # 返回到 app 目录
  cd ..
done
  1. 替换 <GitHub 仓库的 URL> 为你在 GitHub 上创建的远程仓库的 URL 地址。确保每个仓库都有正确的远程仓库地址。

  2. 保存并关闭脚本文件。

  3. 在终端中,进入包含脚本文件的目录,并为脚本文件添加执行权限。可以使用以下命令:

chmod +x upload_to_github.sh
  1. 运行脚本文件,使用以下命令:
./upload_to_github.sh

脚本将自动进入每个仓库目录,并将其推送到对应的远程仓库。你需要在每个仓库的首次推送时提供 GitHub 账户的用户名和密码或访问令牌,以确保权限验证。

2.2 优化版本

如果你希望在脚本中使用固定链接和文件夹名来构建 GitHub 仓库的 URL,你可以对脚本进行以下修改:

#!/bin/bash

# 进入 app 目录
cd ~/code/app

# 遍历 app 目录下的每个文件夹
for repo in */; do
  # 进入每个 Git 仓库目录
  cd "$repo"

  # 获取文件夹名
  folder_name=$(basename "$PWD")

  # 构建远程仓库地址
  repo_url="https://github.com/<你的用户名>/${folder_name}.git"

  # 添加远程仓库地址
  git remote add origin "$repo_url"

  # 推送代码到远程仓库
  git push -u origin master

  # 返回到 app 目录
  cd ..
done

在上述脚本中,你需要将 <你的用户名> 替换为你在 GitHub 上的用户名。

这样,脚本将会根据每个文件夹的名称构建对应的 GitHub 仓库 URL,并将其作为远程仓库地址添加到各个仓库中。

请注意,这种方法假设每个文件夹的名称与对应的 GitHub 仓库名称完全匹配。如果文件夹名称和仓库名称不一致,你可能需要对脚本进行进一步修改以适应你的情况。

希望这次修改能满足你的需求!如果你需要进一步帮助,请随时提问。

三、 GitHub 创建空仓库

3.1 初始版本

你可以使用 shell 脚本通过 GitHub API 在 GitHub 上创建一个空的远程仓库。以下是一个使用 cURL 命令的示例脚本:

#!/bin/bash

# 你的 GitHub 用户名和访问令牌
USERNAME="<你的用户名>"
ACCESS_TOKEN="<你的访问令牌>"

# 仓库名称
REPO_NAME="my-repo"

# 构建 API URL
API_URL="https://api.github.com/user/repos"

# 创建仓库的 JSON 数据
JSON_DATA="{\"name\":\"$REPO_NAME\",\"private\":false}"

# 发送 POST 请求创建仓库
curl -u "$USERNAME:$ACCESS_TOKEN" -d "$JSON_DATA" "$API_URL"

在上述脚本中,你需要将 <你的用户名> 替换为你的 GitHub 用户名,并将 <你的访问令牌> 替换为你的 GitHub 访问令牌。

脚本中使用的 GitHub API 是 /user/repos,它允许你创建一个属于当前用户的新仓库。name 参数指定了仓库名称,private 参数设置为 false 表示创建一个公开仓库。

运行脚本后,它将使用提供的用户名和访问令牌发送一个 POST 请求来创建一个空的远程仓库。

请确保在运行脚本之前安装了 cURL 工具,并且替换脚本中的相应参数。

3.2 优化版本

基于response

server@dev-fj-srv:~/Desktop$ ./create_repo.sh 
{
  "id": 735911698,
  "node_id": "R_kgDOK90fEg",
  "name": "FreemeNotes",
  "full_name": "fangjian98/FreemeNotes",
  "private": false,
  "owner": {
    "login": "fangjian98",
    "id": 59403187,
    "node_id": "MDQ6VXNlcjU5NDAzMTg3",
    "avatar_url": "https://avatars.githubusercontent.com/u/59403187?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/fangjian98",
    "html_url": "https://github.com/fangjian98",
    "followers_url": "https://api.github.com/users/fangjian98/followers",
    "following_url": "https://api.github.com/users/fangjian98/following{/other_user}",
    "gists_url": "https://api.github.com/users/fangjian98/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/fangjian98/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/fangjian98/subscriptions",
    "organizations_url": "https://api.github.com/users/fangjian98/orgs",
    "repos_url": "https://api.github.com/users/fangjian98/repos",
    "events_url": "https://api.github.com/users/fangjian98/events{/privacy}",
    "received_events_url": "https://api.github.com/users/fangjian98/received_events",
    "type": "User",
    "site_admin": false
  },
  "html_url": "https://github.com/fangjian98/FreemeNotes",
  "description": null,
  "fork": false,
  "url": "https://api.github.com/repos/fangjian98/FreemeNotes",
  "forks_url": "https://api.github.com/repos/fangjian98/FreemeNotes/forks",
  "keys_url": "https://api.github.com/repos/fangjian98/FreemeNotes/keys{/key_id}",
  "collaborators_url": "https://api.github.com/repos/fangjian98/FreemeNotes/collaborators{/collaborator}",
  "teams_url": "https://api.github.com/repos/fangjian98/FreemeNotes/teams",
  "hooks_url": "https://api.github.com/repos/fangjian98/FreemeNotes/hooks",
  "issue_events_url": "https://api.github.com/repos/fangjian98/FreemeNotes/issues/events{/number}",
  "events_url": "https://api.github.com/repos/fangjian98/FreemeNotes/events",
  "assignees_url": "https://api.github.com/repos/fangjian98/FreemeNotes/assignees{/user}",
  "branches_url": "https://api.github.com/repos/fangjian98/FreemeNotes/branches{/branch}",
  "tags_url": "https://api.github.com/repos/fangjian98/FreemeNotes/tags",
  "blobs_url": "https://api.github.com/repos/fangjian98/FreemeNotes/git/blobs{/sha}",
  "git_tags_url": "https://api.github.com/repos/fangjian98/FreemeNotes/git/tags{/sha}",
  "git_refs_url": "https://api.github.com/repos/fangjian98/FreemeNotes/git/refs{/sha}",
  "trees_url": "https://api.github.com/repos/fangjian98/FreemeNotes/git/trees{/sha}",
  "statuses_url": "https://api.github.com/repos/fangjian98/FreemeNotes/statuses/{sha}",
  "languages_url": "https://api.github.com/repos/fangjian98/FreemeNotes/languages",
  "stargazers_url": "https://api.github.com/repos/fangjian98/FreemeNotes/stargazers",
  "contributors_url": "https://api.github.com/repos/fangjian98/FreemeNotes/contributors",
  "subscribers_url": "https://api.github.com/repos/fangjian98/FreemeNotes/subscribers",
  "subscription_url": "https://api.github.com/repos/fangjian98/FreemeNotes/subscription",
  "commits_url": "https://api.github.com/repos/fangjian98/FreemeNotes/commits{/sha}",
  "git_commits_url": "https://api.github.com/repos/fangjian98/FreemeNotes/git/commits{/sha}",
  "comments_url": "https://api.github.com/repos/fangjian98/FreemeNotes/comments{/number}",
  "issue_comment_url": "https://api.github.com/repos/fangjian98/FreemeNotes/issues/comments{/number}",
  "contents_url": "https://api.github.com/repos/fangjian98/FreemeNotes/contents/{+path}",
  "compare_url": "https://api.github.com/repos/fangjian98/FreemeNotes/compare/{base}...{head}",
  "merges_url": "https://api.github.com/repos/fangjian98/FreemeNotes/merges",
  "archive_url": "https://api.github.com/repos/fangjian98/FreemeNotes/{archive_format}{/ref}",
  "downloads_url": "https://api.github.com/repos/fangjian98/FreemeNotes/downloads",
  "issues_url": "https://api.github.com/repos/fangjian98/FreemeNotes/issues{/number}",
  "pulls_url": "https://api.github.com/repos/fangjian98/FreemeNotes/pulls{/number}",
  "milestones_url": "https://api.github.com/repos/fangjian98/FreemeNotes/milestones{/number}",
  "notifications_url": "https://api.github.com/repos/fangjian98/FreemeNotes/notifications{?since,all,participating}",
  "labels_url": "https://api.github.com/repos/fangjian98/FreemeNotes/labels{/name}",
  "releases_url": "https://api.github.com/repos/fangjian98/FreemeNotes/releases{/id}",
  "deployments_url": "https://api.github.com/repos/fangjian98/FreemeNotes/deployments",
  "created_at": "2023-12-26T12:41:16Z",
  "updated_at": "2023-12-26T12:41:16Z",
  "pushed_at": "2023-12-26T12:41:16Z",
  "git_url": "git://github.com/fangjian98/FreemeNotes.git",
  "ssh_url": "git@github.com:fangjian98/FreemeNotes.git",
  "clone_url": "https://github.com/fangjian98/FreemeNotes.git",
  "svn_url": "https://github.com/fangjian98/FreemeNotes",
  "homepage": null,
  "size": 0,
  "stargazers_count": 0,
  "watchers_count": 0,
  "language": null,
  "has_issues": true,
  "has_projects": true,
  "has_downloads": true,
  "has_wiki": true,
  "has_pages": false,
  "has_discussions": false,
  "forks_count": 0,
  "mirror_url": null,
  "archived": false,
  "disabled": false,
  "open_issues_count": 0,
  "license": null,
  "allow_forking": true,
  "is_template": false,
  "web_commit_signoff_required": false,
  "topics": [

  ],
  "visibility": "public",
  "forks": 0,
  "open_issues": 0,
  "watchers": 0,
  "default_branch": "main",
  "permissions": {
    "admin": true,
    "maintain": true,
    "push": true,
    "triage": true,
    "pull": true
  },
  "allow_squash_merge": true,
  "allow_merge_commit": true,
  "allow_rebase_merge": true,
  "allow_auto_merge": false,
  "delete_branch_on_merge": false,
  "allow_update_branch": false,
  "use_squash_pr_title_as_default": false,
  "squash_merge_commit_message": "COMMIT_MESSAGES",
  "squash_merge_commit_title": "COMMIT_OR_PR_TITLE",
  "merge_commit_message": "PR_TITLE",
  "merge_commit_title": "MERGE_MESSAGE",
  "network_count": 0,
  "subscribers_count": 0
}

为了优化代码以输出仓库 URL 和成功或失败的提示信息,你可以使用命令替换(command substitution)来捕获 curl 命令的输出,并根据返回状态进行相应的处理。下面是经过修改的示例脚本:

#!/bin/bash

# 你的 GitHub 用户名和访问令牌
USERNAME="<你的用户名>"
ACCESS_TOKEN="<你的访问令牌>"

# 仓库名称
REPO_NAME="my-repo"

# 构建 API URL
API_URL="https://api.github.com/user/repos"

# 创建仓库的 JSON 数据
JSON_DATA="{\"name\":\"$REPO_NAME\",\"private\":false}"

# 发送 POST 请求创建仓库并捕获输出
response=$(curl -s -u "$USERNAME:$ACCESS_TOKEN" -d "$JSON_DATA" "$API_URL")

# 检查返回状态并输出相应信息
if [[ $? -eq 0 ]]; then
  repo_url=$(echo "$response" | grep -o '"html_url": "[^"]*' | grep -o '[^"]*$')
  echo "仓库创建成功!"
  echo "仓库 URL:$repo_url"
else
  echo "仓库创建失败!"
fi

在上述脚本中,-s 参数用于 curl 命令,以静默模式发送请求并隐藏进度信息。$? 是上一个命令的返回状态,我们使用它来检查 curl 命令是否成功执行。grep 命令用于从 curl 输出中提取仓库 URL。

如果 curl 命令成功执行,脚本将提取仓库 URL 并输出成功的提示信息,否则将输出失败的提示信息。

请确保在运行脚本之前安装了 cURL 工具,并且替换脚本中的相应参数。

文章来源:https://blog.csdn.net/weixin_44008788/article/details/135231187
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。