Hello @nethgato
The scenario used in the script below is as follows:
- Create the file “test1/test2” manually on github.com
- Run the script below, which will do the following:
a. Gets the latest commit from github
b. Creates a blob with the name “test1”
c. Creates a tree containing the new blob “test1”
d. Creates a new commit with the new tree
e. Updates the branch to point to the new commit
- Check the commits on github.com, and you can see that the commit was created with 0 changes.
Doing step 2 on github.com (that is, create the file “test1”) will fail with the message:
A file with the same name already exists. Please choose a different name and try again.
Could it be a change in the Trees APIs?
Comparing the newly created tree with the tree before the commit, they turned out the same, that is, the path “test1” is of type tree in both, even though I called the trees API passing the BLOB “test1”, but it didn’t fail (shouldn’t it?).
This explains the empty commit, but doing the opposite scenario through the APIs, have a file “test1” on github and then commit a file “test1/test2”, will also succeed, but this time the file “test1” is lost, it is replaced by the committed file “test1/test2”.
Thank you.
The Script
## Set the following three variables before running the script
OWNER=""
TOKEN=""
REPO=""
## Switching between the API_VERSION and USER_AGENT does not change the behavior
API_VERSION="application/vnd.github.beta+json"
#API_VERSION="application/vnd.github.v3+json"
#USER_AGENT="curl/7.68.0"
USER_AGENT="GitHubJava/2.1.0"
## Retrieve the current HEAD SHA
echo "Retrieving HEAD on master"
currentHead=`curl -v -H "Accept: $API_VERSION" -H "User-Agent: $USER_AGENT" -u $OWNER:$TOKEN https://api.github.com/repos/$OWNER/$REPO/git/refs/heads/master`
currentHeadSha=`echo $currentHead | sed -n 's/.*"sha": *"\([a-z0-9]*\)".*/\1/p'`
echo "currentHead: $currentHead"
echo "currentHeadSha: $currentHeadSha"
## Retrieve the latest tree SHA to be used as the base tree of the new tree to be committed
echo "Retrieving tree-sha of HEAD on $REPO"
currentCommit=`curl -s -H "Accept: $API_VERSION" -H "User-Agent: $USER_AGENT" -u $OWNER:$TOKEN https://api.github.com/repos/$OWNER/$REPO/git/commits/$currentHeadSha`
currentTreeSha=`echo $currentCommit | sed -n 's/.*"tree": *{ *"sha": *"\([a-z0-9]*\)".*/\1/p'`
echo "currentCommit: $currentCommit"
echo "currentTreeSha: $currentTreeSha"
## Just getting the current tree to be compared later to the new tree
echo "Retrieving tree of HEAD on $REPO"
currentTree=`curl -s -H "Accept: $API_VERSION" -H "User-Agent: $USER_AGENT" -u $OWNER:$TOKEN https://api.github.com/repos/$OWNER/$REPO/git/trees/$currentTreeSha`
## Create the new tree containing the BLOB "test1"
echo "Creating new tree with new blob"
data=$(echo "{\"tree\":[{\"path\":\"test1\",\"mode\":\"100644\",\"type\":\"blob\",\"content\":\"bbbbbbbbbbb\"}],\"base_tree\":\"$currentTreeSha\"}")
newTree=`curl -s -X POST -H "Accept: $API_VERSION" -H "User-Agent: $USER_AGENT" -u $OWNER:$TOKEN https://api.github.com/repos/$OWNER/$REPO/git/trees -d "$data"`
newTreeSha=`echo $newTree | sed -n 's/{ *"sha": *"\([a-z0-9]*\)".*/\1/p'`
echo "newTreeSha: $newTreeSha"
## Create the new commit with the new tree
echo "Creating new commit with new tree [$newTreeSha]"
data=$(echo "{\"message\":\"message\",\"tree\":\"$newTreeSha\", \"parents\":[\"$currentHeadSha\"]}")
newCommit=`curl -s -X POST -H "Accept: $API_VERSION" -H "User-Agent: $USER_AGENT" -u $OWNER:$TOKEN https://api.github.com/repos/$OWNER/$REPO/git/commits -d "$data"`
newCommitSha=`echo $newCommit | sed -n 's/{ *"sha": *"\([a-z0-9]*\)".*/\1/p'`
echo "newCommitSha: $newCommitSha"
## Update the branch to point to the new commit
echo "Updating branch to point to new commit [$newCommitSha]"
data=$(echo "{\"sha\":\"$newCommitSha\"}")
newRef=`curl -s -X PATCH -H "Accept: $API_VERSION" -H "User-Agent: $USER_AGENT" -u $OWNER:$TOKEN https://api.github.com/repos/$OWNER/$REPO/git/refs/heads/master -d "$data"`
## Get the new HEAD SHA
newHeadSha=`echo $newRef | sed -n 's/.*"sha": *"\([a-z0-9]*\)".*/\1/p'`
echo "newHeadSha: $newHeadSha"
## If the new HEAD is the new commit, then the commit was created successfully
if [[ "$newHeadSha" == "$newCommitSha" ]]; then
echo "Success"
else
echo "Failure"
echo "newRef: $newRef"
fi
## Print the tree before the commit (currentTree) and the tree after the commit (newTree)
echo $currentTree | python -m json.tool
echo "###############################################"
echo $newTree | python -m json.tool