It is very easy you need to use `git rebase -i HEAD~40` the last number is the amount of commits to go back. then you can group the commits you want to merge (cut and paste the line and put it where it needs to go) set the second commits action (first column) to s (squash) It will then merge those commits, if there are any conflicts in the auto merge it might leave little snippets in the code that you need to manually correct. These will look something like >>>>>>>>>> HEAD old code ======== new code <<<<<<<<<< later commit Fix those, then "git add " git rebase --continue update the commit message for the merged commit and its done! If you want to just remove commits (for example the commit that adds check ubuntu dists, then the other that subsequently removes it) use the same "git rebase -i" command and then just delete the lines for any commits to remove. you can also you the e (edit) action if you ever need to make any change to a particular commit! On 19/12/16 00:31, Jarno Suni wrote: > Is there an easy way to cancel the removing of && so that there is no mention of it in git log disturbing your mind? > > Is it a problem that there are 2 commits that deal with escaping ppa string? If you want less commits I could just commit the final code as one commit. But you did not accept that either. > > > Diff comments: > >> diff --git a/ppa-purge b/ppa-purge >> index a0b5e42..f197c2c 100755 >> --- a/ppa-purge >> +++ b/ppa-purge >> @@ -23,116 +38,196 @@ warn() { >> write_msg "Warning: $*" 1>&2 >> } >> >> +error() { >> + write_msg "Error: $*" 1>&2 >> +} >> + >> +apt_update() { >> + msg "Updating package lists. This might take a while..." >> + $APT $quiet_arg update >> + exit_status=$? >> + [[ $exit_status -eq 0 ]] && >> + msg "Updating package lists finished successfully." || { >> + local -r text="Updating package lists failed; error code $exit_status." >> + if [[ $yes ]]; then >> + error "$text" >> + [[ $quit ]] || exit 5 >> + else >> + warn "$text" >> + [[ $quit ]] || { >> + read -p "Continue anyway (y/n)? " -n 1 -r > Yes, I could remove it, I suppose. > >> + echo >> + [[ $REPLY =~ ^[Yy]$ ]] || exit 5 >> + } >> + fi >> + } >> +} >> + >> +finish() { >> + quit=t >> + rm $PPA_PKGS $REVERTS >> + if [[ $restore && ((${#lists[@]} > 0)) ]]; then >> + msg 'Restoring .list file(s):' >> + for file in "${lists[@]}"; do >> + cp -va "$file".save "$file" >> + done >> + apt_update >> + fi >> +} >> + >> +trap finish 0 >> + >> usage() { >> - echo "Usage: sudo ppa-purge [options] [/ppaname]" >> - echo >> - echo "ppa-purge will reset all packages from a PPA to the standard" >> - echo "versions released for your distribution." >> - echo >> - echo "Options:" >> - echo " -p [ppaname] PPA name to be disabled (default: ppa)" >> - echo " -o [ppaowner] PPA owner" >> - echo " -s [host] Repository server (default: ppa.launchpad.net)" >> - echo " -d [distribution] Override the default distribution choice." >> - echo " -y Pass "-y --force-yes" to apt-get or "-y" to aptitude" >> - echo " -i Reverse preference of apt-get upon aptitude." >> - echo " -h Display this help text" >> - echo >> - echo "Example usage commands:" >> - echo " sudo ppa-purge -o xorg-edgers" >> - echo " will remove https://launchpad.net/~xorg-edgers/+archive/ppa" >> - echo >> - echo " sudo ppa-purge -o sarvatt -p xorg-testing" >> - echo " will remove https://launchpad.net/~sarvatt/+archive/xorg-testing" >> - echo >> - echo " sudo ppa-purge [ppa:]ubuntu-x-swat/x-updates" >> - echo " will remove https://launchpad.net/~ubuntu-x-swat/+archive/x-updates" >> - echo >> - echo "Notice: If ppa-purge fails for some reason and you wish to try again," >> - echo "(For example: you left synaptic open while attempting to run it) simply" >> - echo "uncomment the PPA from your sources, run apt-get update and try again." >> - echo >> + cat << EOF >> +Usage: >> +sudo ppa-purge [options] [ppa:][/] >> +sudo ppa-purge [options] -o [-p ] >> +ppa-purge -h >> + >> +ppa-purge will disable matching repository/repositories and revert packages to >> +versions available from remaining enabled repositories. If the packages are not >> +available from any remaining repositories, they will be removed. Bash completion >> +is supported to make it easy to pick a repository. >> + >> +Options: >> + -h Display this help text >> + -n No action, do not downgrade or remove packages. >> + -q Lessen output of $APT update. >> + -u Skip initial update of package lists. >> + -y Run non-interactively; do not prompt for changes. >> + -d Override the default distribution choice. >> + -s Repository server (default: ppa.launchpad.net) >> + -o PPA owner >> + -p PPA name to be disabled (default: ppa) >> + >> +Exit Code: >> + 0: success >> + 1: syntax error >> + 2: no superuser privileges, even if required >> + 4: given PPA not found in the system >> + 5: $APT error >> + >> +Example usage commands: >> + sudo ppa-purge -o xorg-edgers >> + will remove https://launchpad.net/~xorg-edgers/+archive/ppa >> + >> + sudo ppa-purge -o sarvatt -p xorg-testing >> + will remove https://launchpad.net/~sarvatt/+archive/xorg-testing >> + >> + sudo ppa-purge ppa:ubuntu-x-swat/x-updates >> + will remove https://launchpad.net/~ubuntu-x-swat/+archive/x-updates >> + >> + sudo ppa-purge -s linux.dropbox.com ubuntu/ >> + will remove http://linux.dropbox.com/ubuntu >> + >> +EOF >> exit $1 >> } >> >> +suggest_usage() { >> + msg "Run 'ppa-purge -h' to get help." >> + exit $1 >> +} >> + >> +# escape special characters (http://unix.stackexchange.com/a/209744/111181) >> +escape_regex() { >> + printf '%s' "$1" | sed 's/[.[\*^$()+?{|]/\\&/g' >> +} >> >> # Command line options >> -while getopts "p:o:s:d:yih\?" opt; do >> +while getopts "p:o:s:d:nquyh" opt; do >> case "$opt" in >> p ) PPANAME="$OPTARG" ;; >> o ) PPAOWNER="$OPTARG" ;; >> s ) PPAHOST="$OPTARG" ;; >> d ) DIST="$OPTARG" ;; >> - y ) FORCEINSTALL="true" ;; >> - i ) APTALT="true" ;; >> + n ) simulate='-s' ;; >> + q ) quiet_arg='-q=2' ;; >> + u ) skip_initial_update=t ;; > Sorry, but what? I have not had problems with the option. Lists are up-to-date after successful run of ppa-purge no matter if simulation or not, so it is not needed to run update in the beginning of new run. > >> + y ) yes="$yes_option" ;; >> h ) usage 0; ;; >> - \?) usage 1; ;; >> - * ) warn "Unknown option '$opt'"; usage 1; ;; >> + ? ) error "Unknown option"; suggest_usage 1;; >> esac >> done >> shift $(($OPTIND -1)) >> >> +if [[ ${1-} ]]; then >> + regex='^(ppa:)?([^/:[:space:]]+)(/[^/[:space:]]*)?$' >> + if [[ $1 =~ $regex ]]; then >> + PPAOWNER=$(sed -rn 's#'"$regex"'#\2#p' <<<"$1") >> + postfix=$(sed -rn 's#'"$regex"'#\3#p' <<<"$1") >> + if [[ $postfix ]]; then >> + PPANAME="${postfix:1}" >> + fi >> + else >> + error "Invalid argument:" \'"$1"\' >> + suggest_usage 1 >> + fi >> +fi >> + >> if [ -z "$PPAOWNER" ]; then >> - PPAOWNER=$1 >> + error "Required ppa-name argument was not specified" >> + suggest_usage 1 >> fi >> >> -APTARG="" >> -if [ ! -z "$APTALT" ]; then >> - if [ ! -z "$FORCEINSTALL" ]; then >> - APTARG="-y" >> - fi >> - APT=aptitude; APTALT=apt-get >> +[[ $PPAOWNER =~ ^[^/:[:space:]]+$ ]] || { >> + error "Invalid PPA owner name :" \'"$PPAOWNER"\' >> + exit 1 >> +} >> + >> +if [[ ${PPAHOST+x} ]]; then >> + PPAHOST=${PPAHOST,,} # convert to lowercase >> + [[ $PPAHOST =~ ^[a-z0-9.-]+$ ]] || { >> + error "Invalid PPA host name :" \'"$PPAHOST"\' >> + exit 1 >> + } >> else >> - if [ ! -z "$FORCEINSTALL" ]; then >> - APTARG="-y --force-yes" >> - fi >> - APT=apt-get; APTALT=aptitude >> + PPAHOST="ppa.launchpad.net" >> fi >> >> -if echo $1 | grep -q "^ppa:"; then >> - PPAOWNER=$(echo $1 | sed "s#^ppa:\(.*\)/\(.*$\)#\1#") >> - PPANAME=$(echo $1 | sed "s#^ppa:\(.*\)/\(.*$\)#\2#") >> -else >> - if echo $1 | grep -q "^.*/.*$"; then >> - PPAOWNER=$(echo $1 | sed "s#^\(.*\)/\(.*$\)#\1#") >> - PPANAME=$(echo $1 | sed "s#^\(.*\)/\(.*$\)#\2#") >> - fi >> +if [[ ${PPANAME+x} ]]; then >> + [[ $PPANAME =~ ^[^/[:space:]]*$ ]] || { >> + error "Invalid PPA name :" \'"$PPANAME"\' >> + exit 1 >> + } >> +else >> + PPANAME="ppa" >> fi >> >> -if [ -z "$PPAOWNER" ]; then >> - warn "Required ppa-name argument was not specified" >> - usage 1 >> +if [[ ${DIST+x} ]]; then >> + [[ $DIST =~ ^[^/[:space:]]+$ ]] || { >> + error "Invalid distribution name :" \'"$DIST"\' >> + exit 1 >> + } >> +else >> + DIST=$(lsb_release -c -s) >> fi >> >> -# If not set, using defaults >> -[ -z "$PPAHOST" ] && PPAHOST="ppa.launchpad.net" >> -[ -z "$PPANAME" ] && PPANAME="ppa" >> -[ -z "$DIST" ] && DIST=$(lsb_release -c -s) >> - >> if [ "$(id -u)" != "0" ]; then >> - warn "This script would need superuser privileges, use sudo" >> - usage 1 >> + error "This script would need superuser privileges, use sudo" >> + exit 2 >> fi >> >> -msg "Updating packages lists" >> -if ! $APT update > /dev/null; then >> - warn "$APT update failed for some reason" >> - exit 1 >> -fi >> +[[ $skip_initial_update ]] || apt_update >> >> -msg "PPA to be removed: $PPAOWNER $PPANAME" >> +[[ $PPANAME ]] && >> +ppa_id="$PPAHOST/$PPAOWNER/$PPANAME" || >> +ppa_id="$PPAHOST/$PPAOWNER" >> +msg "Repository to be removed: $ppa_id" >> >> # Make list of all packages in PPA >> -PPA_LIST=/var/lib/apt/lists/${PPAHOST}_${PPAOWNER}_${PPANAME}_*_Packages >> -for LIST in $PPA_LIST; do >> + >> +id=$(tr / _ <<<"$ppa_id") >> +for LIST in /var/lib/apt/lists/"$id"_dists_*_Packages \ >> +/var/lib/apt/lists/"$id"_*_dists_*_Packages; do >> if [ -e $LIST ]; then >> grep "^Package: " $LIST | cut -d " " -f2 | sort >> $PPA_PKGS >> fi >> done >> >> if [ ! -s $PPA_PKGS ]; then >> - warn "Could not find package list for PPA: $PPAOWNER $PPANAME" >> - exit 1 >> + error "Could not find package list for repository $ppa_id" >> + exit 4 >> fi >> >> # Ignore the ppa-purge package >