基于 Linux 的批量上传本地 Git 仓库到 Github 的实践
- 一、需求
- 二、上传本地 Git 仓库
- 2.1 初始版本
- 2.2 优化版本
- 三、 GitHub 创建空仓库
- 3.1 初始版本
- 3.2 优化版本
- 四、Gitee 创建空仓库
一、需求
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 上,可以按照以下步骤进行操作:
-
首先,确保你在 GitHub 上创建了一个空的远程仓库,用于存储你的应用程序仓库。
-
创建一个新的 shell 脚本文件(例如
upload_to_github.sh
),并使用文本编辑器打开它。 -
在脚本文件中,添加以下内容:
#!/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
-
替换
<GitHub 仓库的 URL>
为你在 GitHub 上创建的远程仓库的 URL 地址。确保每个仓库都有正确的远程仓库地址。 -
保存并关闭脚本文件。
-
在终端中,进入包含脚本文件的目录,并为脚本文件添加执行权限。可以使用以下命令:
chmod +x upload_to_github.sh
- 运行脚本文件,使用以下命令:
./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 工具,并且替换脚本中的相应参数。
四、Gitee 创建空仓库
你可以使用 shell 脚本通过 Gitee API 在 Gitee 上创建一个空的远程仓库。以下是一个使用 cURL 命令的示例脚本:
#!/bin/bash
# 你的 Gitee 用户名和访问令牌
USERNAME="<你的用户名>"
ACCESS_TOKEN="<你的访问令牌>"
# 仓库名称
REPO_NAME="my-repo"
# 构建 API URL
API_URL="https://gitee.com/api/v5/user/repos"
# 创建仓库的 JSON 数据
JSON_DATA="{\"name\":\"$REPO_NAME\",\"private\":false}"
# 发送 POST 请求创建仓库
curl -X POST -H "Content-Type: application/json" -H "Authorization: token $ACCESS_TOKEN" -d "$JSON_DATA" "$API_URL"
在上述脚本中,你需要将 <你的用户名>
替换为你的 Gitee 用户名,并将 <你的访问令牌>
替换为你的 Gitee 访问令牌。
脚本中使用的 Gitee API 是 /api/v5/user/repos
,它允许你以当前用户的身份创建一个新的仓库。name
参数指定了仓库名称,private
参数设置为 false
表示创建一个公开仓库。
运行脚本后,它将使用提供的用户名和访问令牌发送一个 POST 请求来创建一个空的远程仓库。
请确保在运行脚本之前安装了 cURL 工具,并且替换脚本中的相应参数。