基于 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 ]]; thenrepo_url=$(echo "$response" | grep -o '"html_url": "[^"]*' | grep -o '[^"]*$')echo "仓库创建成功!"echo "仓库 URL:$repo_url"
elseecho "仓库创建失败!"
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 工具,并且替换脚本中的相应参数。