Created
August 6, 2018 18:04
-
-
Save unleashed/fcaa8899a832b6ba6eef01c5af9e765c to your computer and use it in GitHub Desktop.
scripts that helped me rebase and opensource apisonator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# This script receives a parameter, the revision from which to take | |
# the committer information, and applies that committer information | |
# to the current HEAD. | |
# | |
# N.B.: The machinery uses git commit --amend, so if you have staged | |
# changes you will add them to the commit! This is solvable, but not | |
# worth the effort. | |
value_from_key() | |
{ | |
local str="${1}" | |
local key="${2}" | |
local sep="${3:-:}" | |
echo "${str}" | grep -m 1 "^${key}${sep}" | cut -d"${sep}" -s -f2- | |
} | |
git_show_cmd() { | |
git show --no-patch --pretty="CommitId:%H%nAuthor:%an%nAuthorEmail:%ae%nAuthorDate:%aI%nCommit:%cn%nCommitEmail:%ce%nCommitDate:%cI%nSubject:%s%nBody:%b%n" "${@}" | |
} | |
git_log_cmd() { | |
git log --pretty="CommitId:%H%nAuthor:%an%nAuthorEmail:%ae%nAuthorDate:%aI%nCommit:%cn%nCommitEmail:%ce%nCommitDate:%cI%nSubject:%s%nBody:%b%n" "${@}" | |
} | |
git_patch_id_from() | |
{ | |
echo "${1}" | git patch-id | cut -d' ' -f 1 | |
} | |
git_patch_id() | |
{ | |
local data=$(git show --patch "${1}") | |
git_patch_id_from "${data}" | |
} | |
git_log_one() | |
{ | |
git_log_cmd -n1 "${1}" | |
} | |
git_commit_info() | |
{ | |
local rev="${1}" | |
local data=$(git_show_cmd --patch "${rev}") | |
echo "PatchId:$(git_patch_id_from "${data}")" | |
echo "${data}" | |
} | |
git_log_commit_ids() | |
{ | |
git_log_cmd "${@}" | grep "^CommitId:" | cut -d':' -f2- | |
} | |
# can be used to search both by subject, body, or both at the same time | |
# just specify one or two parameters after the revision | |
git_find_by_commit_msg() | |
{ | |
local rev="${1}" | |
local message="${2}" | |
local body="${3}" | |
local filters="'--grep=^${message}$'" | |
if test "x${body}" = "x"; then | |
git_log_commit_ids --grep="^${message}$" "${rev}" | |
else | |
git_log_commit_ids --grep="^${message}$" --grep="^${body}$" "${rev}" | |
fi | |
} | |
git_find_equivalent() | |
{ | |
local me="${1}" | |
local other="${2}" | |
local data=$(git_commit_info "${me}") | |
local patchid=$(value_from_key "${data}" PatchId) | |
local subject=$(value_from_key "${data}" Subject) | |
local body=$(value_from_key "${data}" Body) | |
local candidates=$(git_find_by_commit_msg "${other}" "${subject}" "${body}") | |
if test "x${candidates}" = "x"; then | |
echo "No luck checking history for commit message, checking picked commit" >&2 | |
# unfortunately git won't offer us a script friendly way to extract this | |
candidates=$(git status | grep -E -e "^N(ext|o) commands? " -B 3 | grep -E -e "^\s+(p|r|e)\w*\s+" | grep -v -E -e "^\s+exec\s+" | tail -n 1 | sed -E -e 's/\s+[a-z]+\s([a-z0-9]+).*/\1/') | |
if test "x${candidates}" = "x"; then | |
echo "No candidates found." >&2 | |
return 1 | |
fi | |
fi | |
echo "Found candidates ${candidates}" >&2 | |
for sha in ${candidates}; do | |
echo "Dealing with '${sha}' candidate" >&2 | |
local other_patchid=$(git_patch_id "${sha}") | |
if test "x${patchid}" = "x${other_patchid}"; then | |
echo Found commit ${sha} >&2 | |
echo "${sha}" | |
return 0 | |
fi | |
done | |
echo "No match. Candidates were: ${candidates}" >&2 | |
return 1 | |
} | |
recommit_as() | |
{ | |
local rev="${1}" | |
echo "Recommitting with committer data from ${rev}" >&2 | |
local data="$(git_log_one "${rev}")" | |
if test "x${data}" = "x"; then | |
return 1 | |
fi | |
local committer="$(value_from_key "${data}" Commit)" | |
local commitemail="$(value_from_key "${data}" CommitEmail)" | |
local commitdate="$(value_from_key "${data}" CommitDate)" | |
GIT_COMMITTER_NAME=\""${committer}"\" \ | |
GIT_COMMITTER_EMAIL=\""${commitemail}"\" \ | |
GIT_COMMITTER_DATE=\""${commitdate}"\" \ | |
git commit --amend --no-edit | |
} | |
usage() | |
{ | |
local name="${1}" | |
echo -e "Usage: ${name} <branch | --from commit_id>\n" >&2 | |
echo "* If branch is specified, we will try to match HEAD to a commit id" >&2 | |
echo " in branch and apply its metadata to HEAD. This could fail." >&2 | |
echo "* If commit_id is specified we will take the specified commit id" >&2 | |
echo " metadata and apply it to HEAD" >&2 | |
} | |
run() | |
{ | |
local name=$(basename "${0}") | |
if test "$#" -eq 1; then | |
local commit_id=$(git_find_equivalent HEAD "${1}") | |
if test "x${commit_id}" = "x"; then | |
echo "Automatic commit matching failed. Find the original commit id" >&2 | |
echo -e "and run this program with:\n" >&2 | |
echo "${name} --from <commit_id>" >&2 | |
return 1 | |
fi | |
recommit_as ${commit_id} | |
elif test "$#" -eq 2; then | |
if test "x${1}" = "x--from"; then | |
echo "going with ${2} as commit id" >&2 | |
recommit_as "${2}" | |
else | |
usage ${name} | |
return 1 | |
fi | |
else | |
usage ${name} | |
return 1 | |
fi | |
} | |
# Commands | |
# | |
pick() { | |
local CID="${1}" | |
echo -e "git cherry-pick ${CID}\ngit-recommit-as --from ${CID}" | |
git cherry-pick ${CID} && git-recommit-as --from ${CID} && echo pick Ok. | |
} | |
merge() { | |
local CID="${1}" | |
local branch="${2-base-oss}" | |
echo -e "git merge --no-edit --no-ff ${branch}\ngit commit --amend -e -C ${CID}\n" | |
echo -e "git-recommit-as --from ${CID}" | |
git merge --no-edit --no-ff ${branch} && git commit --amend -e -C ${CID} && \ | |
git-recommit-as --from ${CID} && echo merge Ok. | |
} | |
rebase() { | |
local CID="${1}" | |
local from="${2-oss}" | |
local where="${3-rebased-oss}" | |
local branch="${4-base-oss}" | |
echo -e "git checkout -f ${branch}\ngit reset --hard ${CID}" | |
echo -e "git rebase -i -p --onto ${where} ${from} ${branch} --exec 'git-recommit-as ${CID}'" | |
git checkout -f ${branch} && git reset --hard ${CID} && \ | |
git rebase -i -p --onto ${where} ${from} ${branch} \ | |
--exec "git-recommit-as ${CID}" && \ | |
echo rebase Ok. | |
} | |
rebase_no_ff() { | |
local merge_cid="${1}" | |
local merge_base=$(git merge-base ${merge_cid}^ ${merge_cid}^2) | |
local other_merge_base="${2-$(git_find_equivalent ${merge_base} rebased-oss)}" | |
local branch="${3-base-oss}" | |
rebase ${merge_cid}^2 ${merge_base} ${other_merge_base} ${branch} | |
} | |
[[ $0 != "$BASH_SOURCE" ]] || (set -euf -o pipefail; run "${@}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment