arthur.sw
arthur.sw

Reputation: 11619

Rename a file with github api?

I thought that the update file method of the Github API could be used to rename a file (by providing the new path as parameter) but it does not seem to work.

The only way to rename is to delete the file and to create a similar one with the new name?

Upvotes: 5

Views: 3798

Answers (4)

maicalal
maicalal

Reputation: 101

For those who end up here looking for more options, there is a better way to rename a file/folder. Please refer to the below link: Rename a file using Azure devops api (should work similar for corresponding github api

Works for folder rename as well. There you would need to specify the folder path for new and old using the same payload structure as in the sample request in above link.

Upvotes: 0

pj5001
pj5001

Reputation: 41

I found this article useful: Renaming files using the GitHub api but it didn't work for me completely. It was duplicating files. Since deleting files is available just through changing the tree I came up with such replacement of the tree in step 3 of that article:

{
    "base_tree": "{yourbaseTreeSHA}",
    "tree": [
      {
        "path": "archive/TF/service/DEV/service_SVCAAA03v3DEV.tf',
        "mode": "100644",
        "type": "blob",
        "sha": "{yourFileTreeSHA}"",
      },
      {
        "path": "TF/service/DEV/service_SVCAAA03v3DEV.tf",
        "mode": "100644",
        "type": "blob",
        "sha": null,
      }
    ],
  }

and it really does the trick. So to have the rename/move of the file done you need to do 5 calls to GitHub API but the result is awesome: view of the commit on github

Upvotes: 4

yaodong
yaodong

Reputation: 404

With the help of the following articles, I figured out how to rename a file with Github API.

First, find and store the tree that latest commit.

# Gem octokir.rb 4.2.0 and Github API v3
api = Octokit::Client.new(access_token: "")
ref = 'heads/master'
repo = 'repo/name'
master_ref = api.ref repo, ref
last_commit = api.commit(repo, master_ref[:object][:sha])
last_tree = api.tree(repo, last_commit[:sha], recursive: true)

Use The harder way described in article Commit a file with the GitHub API to create a new tree. Then, do the rename just like the nodeJs version does and create a new tree based on the below changes.

changed_tree = last_tree[:tree].map(&:to_hash).reject { |blob| blob[:type] == 'tree' }
changed_tree.each { |blob| blob[:path] = new_name if blob[:path] == old_name }
changed_tree.each { |blob| blob.delete(:url) && blob.delete(:size) }
new_tree = api.create_tree(repo, changed_tree)

Create a new commit then point the HEAD to it.

new_commit = api.create_commit(repo, "Rename #{File.basename(old_name)} to #{File.basename(new_name)}", new_tree[:sha], last_commit[:sha])
api.update_ref(repo, ref, new_commit.sha)

That's all.

Upvotes: 2

Ivan Zuzak
Ivan Zuzak

Reputation: 18762

I thought that the update file method of the Github API could be used to rename a file (by providing the new path as parameter) but it does not seem to work.

There's no way to rename a file with a single request to the API.

The only way to rename is to delete the file and to create a similar one with the new name?

That's one way, but the downside is that you get two commits in the history (one for the delete, and one for the create).

A different way is to use the low-level Git API:

https://developer.github.com/v3/git/

With that, you can modify the tree entry containing the blob to list it under a different name, then create a new commit for that tree, and finally update the branch to point to that new commit. The whole process requires more API requests, but you get a single commit for the rename.

Upvotes: 6

Related Questions