Hallo Brian, Brian Gernhardt schrieb am Wed 30. Apr, 11:25 (-0400): > On Apr 30, 2008, at 5:02 AM, Jörg Sommer wrote: > >>> I also dislike the large lists this is carrying around in shell >>> variables. If I'm reading it correctly, the tag list could be >>> replaced >>> by invocations of "git describe --exact-match". >> >> Yes. How to get all tags of a commit? >> >> % git tag foo v1.5.5 >> % git describe --exact-match 9d831805195ba40b62f632acc6bb6e53d3 >> warning: tag 'v1.5.5' is really 'foo' here >> v1.5.5 And how can I get only tags no annotated tags? We can't recreate annotated tags with git rebase. > Those concerns being: overrunning the length of a shell variable, Are you shure there is any such bounding? I didn't saw anything about the size of a variables in IEEE 1003.1-2004, but didn't look very carfully. All my shells (bash, dash, zsh) can handle more than 16777217 characters: dash -c 'a=a; while :; do a=$a$a; echo $a | wc -c; done' This would be a new version of create_extended_todo_list() without tac. What do you think about it? Is it better readable? But there's a bug. create_extended_todo_list () { # The idea of this function is to # 1. build a list of tags # 2. go through the list and # * issue a reset command to the parent of the commit, if the last # commit was not the parent of the current commit, # * issue a pick command for simple commits, # * issue for each merge commit a merge command with the hashs of # the parent commits, # * register each parent of a merge and issue a mark command # (without an ID) after the commit for each registered commit and # * issue a tag command, if the commit is in the tag list. # 3. Then go through the created list and # * add an ID to each mark command and # * replace all occurences of the hash in reset and merge commands # by the mark ID test -e "$DOTEST"/cetl.tmp \ && die "Someone else uses our filename cetl.tmp." \ "That's not nice" if test t = "${PRESERVE_TAGS:-}" then tag_list=$(git show-ref --abbrev=7 --tags | \ ( while read sha1 tag do tag=${tag#refs/tags/} if test ${last_sha1:-0000} = $sha1 then saved_tags="$saved_tags:$tag" else printf "%s" "${last_sha1:+ $last_sha1#$saved_tags}" last_sha1=$sha1 saved_tags=$tag fi done echo "${last_sha1:+ $last_sha1:$saved_tags}" ) ) else tag_list= fi mark_these_commits= while IFS=_ read commit parents subject do first_parent=${parents%% *} if test "${last_commit:-$SHORTUPSTREAM}" != $first_parent then test "$first_parent" = $SHORTUPSTREAM && first_parent=$SHORTONTO echo reset $first_parent fi unset first_parent last_commit=$commit case "$parents" in *' '*) new_parents= for p in $parents do mark_these_commits=$(insert_value_at_key_into_list \ "$commit" "$p" "$mark_these_commits") if test "$p" = $SHORTUPSTREAM then new_parents="$new_parents $SHORTONTO" else new_parents="$new_parents $p" fi done unset p echo merge $commit ${new_parents# * } unset new_parents ;; *) echo "pick $commit $subject" ;; esac if tmp=$(get_value_from_list $commit "$tag_list") then for t in $(echo $tmp | tr : ' ') do echo tag $t done fi done > "$DOTEST"/cetl.tmp unset commit parents subject commit_mark_list= next_mark=0 last_commit= while read cmd args do case "$cmd" in pick) this_commit="${args%% *}" ;; reset) this_commit=$args if tmp=$(get_value_from_list $args "$commit_mark_list") then args=":$tmp" fi ;; merge) new_args= for i in ${args#* } do if tmp=$(get_value_from_list $i \ "$commit_mark_list") then new_args="$new_args :$tmp" else new_args="$new_args $i" fi done this_commit="${args%% *}" args="$this_commit ${new_args# }" ;; esac if tmp=$(get_value_from_list "$last_commit" \ "$mark_these_commits") && \ test "${this_commit:-$last_commit}" != $tmp then if tmp=$(get_value_from_list "$last_commit" \ "$commit_mark_list") then test "$last_cmd" = reset -o "$last_cmd" = tag \ || echo mark ":$tmp" else commit_mark_list=$(insert_value_at_key_into_list \ $next_mark $last_commit "$commit_mark_list") echo mark ":$next_mark" next_mark=$(($next_mark + 1)) fi fi last_commit=${this_commit:-$last_commit} unset this_commit echo "$cmd $args" last_cmd=$cmd done < "$DOTEST"/cetl.tmp rm "$DOTEST"/cetl.tmp unset last_cmd last_commit next_mark cmd args tmp commit_mark_list \ mark_these_commits } The problem is the mark command. If you walk from ONTO to HEAD trough the list, you must know for a commit, if it is used _later_. But don't create a mark if it is used immediately, e.g. pick; merge not pick; mark; merge. If you walk from HEAD to ONTO, this is much easier. I delayed the mark for the first head of a merge and checked if the next commit is this commit. This way I keep the todo list clean and don't get something like this for --first-parent: pick abc pick def mark :0 merge 012 foreign-branch Bye, Jörg. -- Es ist außerdem ein weit verbreiteter Irrtum das USENET ‚helfen‘ soll. Tatsächlich wurde USENET nachweislich zur persönlichen Belustigung seiner Erfinder geschaffen. Jörg Klemenz <joerg@xxxxxxx>, <b4ai4o$1u8vmt$2@xxxxxxxxxxxxxxxxxxxxxxx>
Attachment:
signature.asc
Description: Digital signature http://en.wikipedia.org/wiki/OpenPGP