My previous answer was not working well.
Here is an alternative approach.
One major issue with these approaches is that the Gerrit UI needs to be refreshed for each patch inorder for Gerrit to accept the new state.
I will try to show the steps with real examples. Please replace the Branches/Names/Projects etc based on your usecase
Scenario
Gerrit Project: LineageOS/android_packages_apps_Settings
Gerrit URL: https://localhost:8443
Gerrit SSH alias: lgerrit
(This is the Gerrit's SSH config set in ~/.ssh/config
)
Gerrit Branch: refs/heads/lineage-19.1
Gerrit Push Branch: refs/for/lineage-19.1
Currently I have 100+ commits that are status: merged
in gerrit for this project.
All my refs/for/lineage-19.1
are equal to refs/heads/lineage-19.1
as all commits are merged.
There are few status: open
commits that were used to debug stuff. I want to preserve these commits for future
Task
I want to UNMERGE the 100+ commits, WITHOUT creating a new branch.
I want to reset my refs/heads/lineage-19.1
branch to the UPSTREAM lineage-19.1 branch.
I want all my 100+ commits to be status: open
on top of `refs/heads/lineage-19.1
Steps
Prerequisites:
You need to have access to the gerrit server.
You need to install the screen
package.
1) Force reset refs/heads/lineage-19.1
to Upstream lineage-19.1
git push lgerrit:LineageOS/android_packages_apps_Settings LineageOS/lineage-19.1:refs/heads/lineage-19.1 -f -o skip-validation=true
Here if i try to push my status, we get an error that the chnges are closed, which is as expected:
remote: commit b2a1a05: warning: subject >50 characters; use shorter first paragraph
To lgerrit:LineageOS/android_packages_apps_Settings
! [remote rejected] HEAD -> refs/for/lineage-19.1 (change https://localhost:8443/c/LineageOS/android_packages_apps_Settings/+/19 closed)
error: failed to push some refs to 'lgerrit:LineageOS/android_packages_apps_Settings'
2) STOP the gerrit server gerrit.sh stop
From Now we are in our gerrit server
3) Navigate to the Project's folder in your Gerrit server and run a git gc
I did this as I think it puts all the refs/changes mappings in packed-refs
which is needed later on
~/gerrit/git/LineageOS/android_packages_apps_Settings.git 10s
❯ git gc
Enumerating objects: 978412, done.
Counting objects: 100% (978412/978412), done.
Delta compression using up to 10 threads
Compressing objects: 100% (167229/167229), done.
Writing objects: 100% (978412/978412), done.
Selecting bitmap commits: 118017, done.
Building bitmaps: 100% (328/328), done.
Total 978412 (delta 631271), reused 978344 (delta 631203), pack-reused 0
4) Write a bash function to export all changes that are MERGED (delimited by a :
export_merged() {
for i in $(grep meta packed-refs | cut -d' ' -f2)
do
echo "$i:$(git log --oneline $i --grep='autogenerated:gerrit:merged')" | grep patch
done | cut -d' ' -f1
}
5) Export merged commits to a text file
$ export_merged | tee /tmp/export_merged.txt
refs/changes/01/101/meta:d9971cb5b4
refs/changes/02/102/meta:f9e2c6c713
refs/changes/02/2/meta:bafba9cb72
...
6) Write a test loop that updates the refs from above to one commit behind the current commit. i.e refs/changes/01/101/meta~1
for i in $(cat /tmp/export_merged.txt); do
REF="$(echo $i | cut -d':' -f1)"
MERGED="$(echo $i | cut -d':' -f2)"
NEWREF="$(git rev-parse $MERGED~1)"
echo git update-ref $REF $NEWREF
done
The output will be like:
git update-ref refs/changes/01/101/meta 71bb5ae0eebc0b3696fef22260cb121ff1045b82
git update-ref refs/changes/02/102/meta 952501d0bc52e44c0e022928dc52fc6ccc3b6254
...
7) IMPORTANT Verify that the commit hash matches refs/changes/xx/yy/meta~1
In my case it does:
$ git rev-parse refs/changes/01/101/meta~1
71bb5ae0eebc0b3696fef22260cb121ff1045b82
If it does not, stop here and ABORT.
8) Backup packed-refs file somewhere safe.
9) If all looks good, remove the echo
from the for
loop above and run git gc
again
for i in $(cat /tmp/export_merged.txt); do
REF="$(echo $i | cut -d':' -f1)"
MERGED="$(echo $i | cut -d':' -f2)"
NEWREF="$(git rev-parse $MERGED~1)"
git update-ref $REF $NEWREF
done
git gc
Now the packed-refs file will change. Here is the diff in my case:
$ diff packed-refs /tmp/packed-refsback | head -n4
8c8
< 71bb5ae0eebc0b3696fef22260cb121ff1045b82 refs/changes/01/101/meta
---
> d9971cb5b4c4e5b8a8311f2d5c50eeba08b86f84 refs/changes/01/101/meta
...
10) Start gerrit And flush caches
ssh lgerrit gerrit flush-caches --all
Making GERRIT notice the new changes.
Gerrit for some reason still thinks that the changes are merged. This is fixed when you open the change from the UI however that is cumbersome for large number of changes.
Here you see gerrit still rejecting my push.
To lgerrit:LineageOS/android_packages_apps_Settings
! [remote rejected] HEAD -> refs/for/lineage-19.1 (change https://localhost:8443/c/LineageOS/android_packages_apps_Settings/+/19 closed)
error: failed to push some refs to 'lgerrit:LineageOS/android_packages_apps_Settings'
Then I open my browser and simply visit this change. Notice the change 19 is no longer error-ing out but it is the next change number 20.
To lgerrit:LineageOS/android_packages_apps_Settings
! [remote rejected] HEAD -> refs/for/lineage-19.1 (change https://localhost:8443/c/LineageOS/android_packages_apps_Settings/+/20 closed)
error: failed to push some refs to 'lgerrit:LineageOS/android_packages_apps_Settings'
So we need to load all the changes for gerrit to reflect the new status. A curl
on the change url does not work, but we need another URL.
Last step: Loop through ALL changes in project through curl asynchronously
Note Change your Project URL accordingly. Notice the %2F
replacing /
!
for i in $(grep meta packed-refs| cut -d' ' -f2)
do
CHANGE=$(basename $(dirname $i))
screen -d -m curl -s "https://localhost:8443/changes/LineageOS%2Fandroid_packages_apps_Settings~$CHANGE/revisions/current/mergeable" -k -o /tmp/log
sleep 0.1
done
Results :)
remote: https://localhost:8443/c/LineageOS/android_packages_apps_Settings/+/148 SoftAp: add back AP Band preference into tether settings
remote:
To lgerrit:LineageOS/android_packages_apps_Settings
* [new reference] HEAD -> refs/for/lineage-19.1
Helper script: Link