55JSON_MODE=false
66SHORT_NAME=" "
77BRANCH_NUMBER=" "
8+ USE_TIMESTAMP=false
89ARGS=()
910i=1
1011while [ $i -le $# ]; do
1112 arg=" ${! i} "
1213 case " $arg " in
13- --json)
14- JSON_MODE=true
14+ --json)
15+ JSON_MODE=true
1516 ;;
1617 --short-name)
1718 if [ $(( i + 1 )) -gt $# ]; then
@@ -40,30 +41,35 @@ while [ $i -le $# ]; do
4041 fi
4142 BRANCH_NUMBER=" $next_arg "
4243 ;;
43- --help|-h)
44- echo " Usage: $0 [--json] [--short-name <name>] [--number N] <feature_description>"
44+ --timestamp)
45+ USE_TIMESTAMP=true
46+ ;;
47+ --help|-h)
48+ echo " Usage: $0 [--json] [--short-name <name>] [--number N] [--timestamp] <feature_description>"
4549 echo " "
4650 echo " Options:"
4751 echo " --json Output in JSON format"
4852 echo " --short-name <name> Provide a custom short name (2-4 words) for the branch"
4953 echo " --number N Specify branch number manually (overrides auto-detection)"
54+ echo " --timestamp Use timestamp prefix (YYYYMMDD-HHMMSS) instead of sequential numbering"
5055 echo " --help, -h Show this help message"
5156 echo " "
5257 echo " Examples:"
5358 echo " $0 'Add user authentication system' --short-name 'user-auth'"
5459 echo " $0 'Implement OAuth2 integration for API' --number 5"
60+ echo " $0 --timestamp --short-name 'user-auth' 'Add user authentication'"
5561 exit 0
5662 ;;
57- * )
58- ARGS+=(" $arg " )
63+ * )
64+ ARGS+=(" $arg " )
5965 ;;
6066 esac
6167 i=$(( i + 1 ))
6268done
6369
6470FEATURE_DESCRIPTION=" ${ARGS[*]} "
6571if [ -z " $FEATURE_DESCRIPTION " ]; then
66- echo " Usage: $0 [--json] [--short-name <name>] [--number N] <feature_description>" >&2
72+ echo " Usage: $0 [--json] [--short-name <name>] [--number N] [--timestamp] <feature_description>" >&2
6773 exit 1
6874fi
6975
@@ -96,10 +102,13 @@ get_highest_from_specs() {
96102 for dir in " $specs_dir " /* ; do
97103 [ -d " $dir " ] || continue
98104 dirname=$( basename " $dir " )
99- number=$( echo " $dirname " | grep -o ' ^[0-9]\+' || echo " 0" )
100- number=$(( 10 #$number ))
101- if [ " $number " -gt " $highest " ]; then
102- highest=$number
105+ # Only match sequential prefixes (###-*), skip timestamp dirs
106+ if echo " $dirname " | grep -q ' ^[0-9]\{3\}-' ; then
107+ number=$( echo " $dirname " | grep -o ' ^[0-9]\{3\}' )
108+ number=$(( 10 #$number ))
109+ if [ " $number " -gt " $highest " ]; then
110+ highest=$number
111+ fi
103112 fi
104113 done
105114 fi
@@ -242,29 +251,42 @@ else
242251 BRANCH_SUFFIX=$( generate_branch_name " $FEATURE_DESCRIPTION " )
243252fi
244253
245- # Determine branch number
246- if [ -z " $BRANCH_NUMBER " ]; then
247- if [ " $HAS_GIT " = true ]; then
248- # Check existing branches on remotes
249- BRANCH_NUMBER=$( check_existing_branches " $SPECS_DIR " )
250- else
251- # Fall back to local directory check
252- HIGHEST=$( get_highest_from_specs " $SPECS_DIR " )
253- BRANCH_NUMBER=$(( HIGHEST + 1 ))
254- fi
254+ # Warn if --number and --timestamp are both specified
255+ if [ " $USE_TIMESTAMP " = true ] && [ -n " $BRANCH_NUMBER " ]; then
256+ >&2 echo " [specify] Warning: --number is ignored when --timestamp is used"
257+ BRANCH_NUMBER=" "
255258fi
256259
257- # Force base-10 interpretation to prevent octal conversion (e.g., 010 → 8 in octal, but should be 10 in decimal)
258- FEATURE_NUM=$( printf " %03d" " $(( 10 #$BRANCH_NUMBER )) " )
259- BRANCH_NAME=" ${FEATURE_NUM} -${BRANCH_SUFFIX} "
260+ # Determine branch prefix
261+ if [ " $USE_TIMESTAMP " = true ]; then
262+ FEATURE_NUM=$( date +%Y%m%d-%H%M%S)
263+ BRANCH_NAME=" ${FEATURE_NUM} -${BRANCH_SUFFIX} "
264+ else
265+ # Determine branch number
266+ if [ -z " $BRANCH_NUMBER " ]; then
267+ if [ " $HAS_GIT " = true ]; then
268+ # Check existing branches on remotes
269+ BRANCH_NUMBER=$( check_existing_branches " $SPECS_DIR " )
270+ else
271+ # Fall back to local directory check
272+ HIGHEST=$( get_highest_from_specs " $SPECS_DIR " )
273+ BRANCH_NUMBER=$(( HIGHEST + 1 ))
274+ fi
275+ fi
276+
277+ # Force base-10 interpretation to prevent octal conversion (e.g., 010 → 8 in octal, but should be 10 in decimal)
278+ FEATURE_NUM=$( printf " %03d" " $(( 10 #$BRANCH_NUMBER )) " )
279+ BRANCH_NAME=" ${FEATURE_NUM} -${BRANCH_SUFFIX} "
280+ fi
260281
261282# GitHub enforces a 244-byte limit on branch names
262283# Validate and truncate if necessary
263284MAX_BRANCH_LENGTH=244
264285if [ ${# BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then
265286 # Calculate how much we need to trim from suffix
266- # Account for: feature number (3) + hyphen (1) = 4 chars
267- MAX_SUFFIX_LENGTH=$(( MAX_BRANCH_LENGTH - 4 ))
287+ # Account for prefix length: timestamp (15) + hyphen (1) = 16, or sequential (3) + hyphen (1) = 4
288+ PREFIX_LENGTH=$(( ${# FEATURE_NUM} + 1 ))
289+ MAX_SUFFIX_LENGTH=$(( MAX_BRANCH_LENGTH - PREFIX_LENGTH))
268290
269291 # Truncate suffix at word boundary if possible
270292 TRUNCATED_SUFFIX=$( echo " $BRANCH_SUFFIX " | cut -c1-$MAX_SUFFIX_LENGTH )
@@ -283,7 +305,11 @@ if [ "$HAS_GIT" = true ]; then
283305 if ! git checkout -b " $BRANCH_NAME " 2> /dev/null; then
284306 # Check if branch already exists
285307 if git branch --list " $BRANCH_NAME " | grep -q . ; then
286- >&2 echo " Error: Branch '$BRANCH_NAME ' already exists. Please use a different feature name or specify a different number with --number."
308+ if [ " $USE_TIMESTAMP " = true ]; then
309+ >&2 echo " Error: Branch '$BRANCH_NAME ' already exists. Rerun to get a new timestamp or use a different --short-name."
310+ else
311+ >&2 echo " Error: Branch '$BRANCH_NAME ' already exists. Please use a different feature name or specify a different number with --number."
312+ fi
287313 exit 1
288314 else
289315 >&2 echo " Error: Failed to create git branch '$BRANCH_NAME '. Please check your git configuration and try again."
0 commit comments