> From: Alcolo Alcolo <alcol...@gmail.com> > My git history is complex and it's a nightmare to rebase from old commits.
I'm not sure what you're attempting to do, but this might help. It's a rebasing script I wrote. It appears that it was based on something Junio wrote. The concept is that it rebases the current branch, but unlike the standard git-rebase, it replicates the merging structure between the merge-base commit and the head of the branch. (IIRC, the standard git-rebase creates a linear branch based on some ordering of the commits in the old branch.) Dale ---------------------------------------------------------------------- #!/bin/bash # # Copyright (c) 2010 Junio C Hamano. # Modified by Dale R. Worley. # Usage: git-rebase--merge-safe <onto> # # Rebase the current branch to commit/branch <onto>, replicating the commit # graph between HEAD and the merge base. . git-sh-setup prec=4 set -ex # Ensure the work tree is clean. require_clean_work_tree "rebase" "Please commit or stash them." onto_name=$1 onto=$(git rev-parse --verify "${onto_name}^0") || die "Does not point to a valid commit: $1" head_name=$( git symbolic-ref HEAD ) orig_head=$(git rev-parse --verify $head_name) || exit 1 echo onto=$onto echo head_name=$head_name echo orig_head=$orig_head # Get the merge base, which is the root of the branch that we are rebasing. # (For now, ignore the question of whether there is more than one merge base.) mb=$(git merge-base "$onto" "$orig_head") echo mb=$mb # Get the list of commits to rebase, which is everything between $mb and # $orig_head. # Note that $mb is not included. revisions=`git rev-list --reverse --ancestry-path $mb..$orig_head` echo revisions=$revisions # Set up the list mapping the commits on the original branch to the commits # on the branch we are creating. # Its format is ",old-hash1/new-hash1,old-hash2/new-hash2,...,". # The initial value maps $mb to $onto. map=",$mb/$onto," # Export these so git commit can see them. export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE # Process each commit in forward topological order. for cmt in $revisions do # Examine the commit to extract information we will need to reconstruct it. # First parent of the commit that has a mapping, i.e., is part of the # branch (and has thus been rebuilt already. first_mapped_parent= # The new commit that was made of $first_mapped_parent. first_mapped_parent_mapped= # List of -p options naming the parent commits, or their new commits if they # are in the branch. parents= # Dissect the old commit's data. # Output the commit data into FD 3. exec 3< <( git cat-file commit $cmt ) while read keyword rest <&3 do case $keyword in tree) # Ignored ;; parent) # See if the parent is mapped, i.e., is in the # original branch. if [[ "$map" == *,$rest/* ]] then # This parent has been mapped. Get the new commit. parent_mapped=${map#*,$rest/} parent_mapped=${parent_mapped%%,*} if test -z "$first_mapped_parent" then first_mapped_parent=$rest first_mapped_parent_mapped=$parent_mapped fi else # This parent has not been mapped. parent_mapped=$rest fi # $parent_mapped is a parent of the new commit. parents="$parents -p $parent_mapped" ;; author) # Extract the information about the author. GIT_AUTHOR_NAME="${rest%% <*}" GIT_AUTHOR_EMAIL="${rest##* <}" GIT_AUTHOR_EMAIL="${GIT_AUTHOR_EMAIL%%> *}" GIT_AUTHOR_DATE="${rest##*> }" ;; committer) # Ignored: The new commit will have this user's name # as committer. ;; '') # End of fixed fields, remainder is the commit comment. # Leave contents of FD 3 queued to be read later by # git commit-tree. break ;; *) # Ignore all other keywords. ;; esac done echo GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" echo GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" echo GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" echo parents="$parents" echo first_mapped_parent=$first_mapped_parent echo first_mapped_parent_mapped=$first_mapped_parent_mapped test -n "$first_mapped_parent" || exit 1 # Do the three-way merge. # Empty the index so git read-tree will merge into it. git read-tree --empty git read-tree -m --aggressive \ $first_mapped_parent $cmt $first_mapped_parent_mapped git merge-index git-merge-one-file -a # Construct the file tree for the new commit. tree=$( git write-tree ) # Create the new commit # Note that FD 3 contains the remainder of the commit description # from the git cat-file above. new_commit=$( git commit-tree $tree $parents <&3 ) echo new_commit=$new_commit # Add the new commit to the map. map="$map$cmt/$new_commit," done echo Final commit is $new_commit # Update the branch pointers. git update-ref ORIG_HEAD $orig_head git update-ref $head_name $new_commit # Go to the new head of the branch. git checkout ${head_name#refs/heads/} ---------------------------------------------------------------------- -- You received this message because you are subscribed to the Google Groups "Git for human beings" group. To unsubscribe from this group and stop receiving emails from it, send an email to git-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.