Was "Re: [RFC] Proposed Git Workflow for Permanent History, Explicit Branch Status, and Developer Continuity" now "Skybuck's GitFlow"
From: Skybuck Flying <hidden>
Date: 2025-08-29 19:42:53
Version 0.08 of Skybuck's Gitflow is now available, all source code below:
Save program 1 as "git-back-to.dpr":
program git_back_to;
{
Skybuck's GitFlow
version 0.08 created on 29 august 2025 by Skybuck Flying and Gemini (AI) and Co-Pilot (AI).
credits:
Almost all code by Google Gemini 2.5 Pro.
GetBranchVersionDigits code by Microsoft Co-Pilot.
Software Idea and Prompting and Overwatching the AI: Skybuck Flying.
improvements for version 0.08:
+ local git support
+ better contribution number
Delphi code developed for Delphi 12.3 and Windows 11.
}
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
System.RegularExpressions,
System.IOUtils,
Winapi.Windows,
ActiveX,
MSXML;
function ExecuteCommand(const Command: string; out Output: TStringList): Integer;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
hRead, hWrite: THandle;
Buffer: array[0..1023] of AnsiChar;
BytesRead: DWord;
Cmd: string;
FullOutput: AnsiString;
begin
Output := TStringList.Create;
Result := -1;
FullOutput := '';
SA.nLength := SizeOf(TSecurityAttributes);
SA.bInheritHandle := True;
SA.lpSecurityDescriptor := nil;
if not CreatePipe(hRead, hWrite, @SA, 0) then
begin
Exit;
end;
try
FillChar(SI, SizeOf(TStartupInfo), 0);
SI.cb := SizeOf(TStartupInfo);
SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
SI.hStdOutput := hWrite;
SI.hStdError := hWrite;
SI.wShowWindow := SW_HIDE;
Cmd := 'cmd.exe /C ' + Command;
if not CreateProcess(nil, PChar(Cmd), nil, nil, True, 0, nil, nil, SI, PI) then
begin
Exit;
end;
CloseHandle(hWrite);
try
while True do
begin
if not ReadFile(hRead, Buffer, SizeOf(Buffer) - 1, BytesRead, nil) or (BytesRead = 0) then
begin
break;
end;
Buffer[BytesRead] := #0;
FullOutput := FullOutput + AnsiString(Buffer);
end;
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, Cardinal(Result));
finally
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end;
finally
CloseHandle(hRead);
end;
Output.Text := string(FullOutput);
end;
function GetBranchVersionDigits: Integer;
var
XMLDoc: IXMLDOMDocument2;
Node: IXMLDOMNode;
ConfigPath: string;
CoInitResult: HRESULT;
begin
Result := 4; // Default value
ConfigPath := ExtractFilePath(ParamStr(0)) + 'SkybuckGitflow.cfg';
if FileExists(ConfigPath) then
begin
// Initialize COM for this thread
CoInitResult := CoInitialize(nil);
try
try
XMLDoc := CoDOMDocument60.Create;
if not Assigned(XMLDoc) then
begin
raise Exception.Create('Failed to create MSXML 6.0 document');
end;
XMLDoc.async := False;
if not XMLDoc.load(ConfigPath) then
begin
// Check for a parse error object before accessing its properties
if Assigned(XMLDoc.parseError) then
begin
raise Exception.Create('XML load failed: ' + XMLDoc.parseError.reason)
end
else
begin
raise Exception.Create('XML load failed with an unknown error.');
end;
end;
Node := XMLDoc.selectSingleNode('//BranchVersionDigits');
if Assigned(Node) then
begin
Result := StrToIntDef(Node.text, 4);
end;
except
on E: Exception do
begin
Writeln('Error processing config file: ', E.Message);
end;
end;
finally
// *** THE FIX IS HERE ***
// Release COM objects BEFORE CoUninitialize is called.
Node := nil;
XMLDoc := nil;
// Uninitialize COM only if it was successfully initialized on this call.
if SUCCEEDED(CoInitResult) then // Use SUCCEEDED for robustness
begin
CoUninitialize;
end;
end;
end;
end;
function RemoteOriginExists: boolean;
var
Output: TStringList;
begin
Output := TStringList.Create;
try
Result := ExecuteCommand('git remote get-url origin > NUL 2>&1', Output) = 0;
finally
Output.Free;
end;
end;
function GetGitConfigValue(const ConfigKey: string): string;
var
Output: TStringList;
begin
Result := '';
Output := TStringList.Create;
try
if ExecuteCommand('git config ' + ConfigKey, Output) = 0 then
begin
if Output.Count > 0 then
begin
Result := Trim(Output.Text);
end;
end;
finally
Output.Free;
end;
end;
function Slugify(const Input: string): string;
begin
Result := Input.ToLower;
Result := TRegEx.Replace(Result, '[^a-z0-9]+', '-');
Result := TRegEx.Replace(Result, '^-+|-+$', '');
if Length(Result) > 50 then
begin
Result := Copy(Result, 1, 50);
end;
end;
function GetNextContributionNumber(const UserPrefix: string; ParaRemoteExists: boolean): Integer;
var
Output: TStringList;
MaxNum: Integer;
Match: TMatch;
Num: Integer;
S, vRefs: string;
begin
MaxNum := 0;
Output := TStringList.Create;
try
if ParaRemoteExists then
begin
ExecuteCommand('git fetch origin --prune', Output); // Sync with remote
Output.Clear;
vRefs := 'refs/heads refs/remotes/origin';
end
else
begin
vRefs := 'refs/heads';
end;
if ExecuteCommand('git for-each-ref --format="%(refname:short)" ' + vRefs, Output) = 0 then
begin
S := Output.Text;
for Match in TRegEx.Matches(S, '^' + UserPrefix + 'Contribution(\d+)-') do
begin
if Match.Success then
begin
Num := StrToIntDef(Match.Groups[1].Value, 0);
if Num > MaxNum then
begin
MaxNum := Num;
end;
end;
end;
end;
finally
Output.Free;
end;
Result := MaxNum + 1;
end;
function TagExists(const ParaTagName: string; ParaRemoteExists: boolean): boolean;
var
vOutput: TStringList;
begin
Result := False;
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Result := True;
Exit;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git ls-remote --tags origin "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Result := vOutput.Text <> '';
end;
end;
finally
vOutput.Free;
end;
end;
function BranchExists(const ParaBranchName: string; ParaRemoteExists: boolean): boolean;
var
vOutput: TStringList;
begin
Result := False;
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/heads/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
Exit;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git show-ref --verify "refs/remotes/origin/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
end;
end;
finally
vOutput.Free;
end;
end;
var
vOldTagName, vDescription, vUserPrefix, vSlug, vNewBranchName, vFormatStr: string;
vNextNum, vBranchVersionDigits: Integer;
vOutput: TStringList;
vRemoteExists: Boolean;
begin
try
vBranchVersionDigits := GetBranchVersionDigits;
if ParamCount <> 2 then
begin
Writeln('Usage: git-back-to <tagname_of_old_commit> "<new_branch_description>"');
Writeln('Example: git-back-to merged/AI0001Contribution007-OldAPIDesign "Re-evaluate V1 API for performance"');
ExitCode := 1;
Exit;
end;
vOldTagName := ParamStr(1);
vDescription := ParamStr(2);
vRemoteExists := RemoteOriginExists;
vUserPrefix := GetGitConfigValue('user.contributionPrefix');
if vUserPrefix = '' then
begin
vUserPrefix := GetGitConfigValue('user.name');
if vUserPrefix <> '' then
begin
vUserPrefix := TRegEx.Replace(vUserPrefix, '[^a-zA-Z0-9]', '');
end
else
begin
Writeln('Error: Git user.name or user.contributionPrefix not set.');
Writeln('Run: git config --global user.name "Your Name"');
Writeln('Or: git config --global user.contributionPrefix "YourPrefix"');
ExitCode := 1;
Exit;
end;
end;
vSlug := Slugify(vDescription);
if vSlug = '' then
begin
Writeln('Error: Description resulted in empty slug.');
ExitCode := 1;
Exit;
end;
if not TagExists(vOldTagName, vRemoteExists) then
begin
Writeln('Error: Tag ''' + vOldTagName + ''' does not exist locally or remotely.');
ExitCode := 1;
Exit;
end;
vNextNum := GetNextContributionNumber(vUserPrefix, vRemoteExists);
vFormatStr := Format('%%sContribution%%0.%dd-%%s', [vBranchVersionDigits]);
vNewBranchName := Format(vFormatStr, [vUserPrefix, vNextNum, vSlug]);
if BranchExists(vNewBranchName, vRemoteExists) then
begin
Writeln('Error: Branch ''' + vNewBranchName + ''' already exists.');
ExitCode := 1;
Exit;
end;
vOutput := TStringList.Create;
try
Writeln('Creating new branch ''' + vNewBranchName + ''' from tag ''' + vOldTagName + '''...');
if ExecuteCommand('git checkout -b "' + vNewBranchName + '" "' + vOldTagName + '"', vOutput) <> 0 then
begin
Writeln('Error: Failed to create branch from tag.');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
if vRemoteExists then
begin
Writeln('Pushing ''' + vNewBranchName + ''' to remote...');
if ExecuteCommand('git push -u origin "' + vNewBranchName + '"', vOutput) <> 0 then
begin
Writeln('Error: Failed to push branch to origin.');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
end;
Writeln('---');
Writeln('Calling git-set-active to mark as active...');
if ExecuteCommand('cmd.exe /c "' + ExtractFilePath(ParamStr(0)) + 'git-set-active.exe" ' + vNewBranchName, vOutput) <> 0 then
begin
Writeln('Warning: Could not mark branch active. Run manually: git-set-active ' + vNewBranchName);
end;
Writeln(vOutput.Text);
finally
vOutput.Free;
end;
Writeln('');
Writeln('Branch ''' + vNewBranchName + ''' successfully created and activated from tag ''' + vOldTagName + '''.');
Writeln('To upgrade it against latest master, use: git-the-future');
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ExitCode := 1;
end;
end;
end.
Save program 2 as "git-new-contribution.dpr":
program git_new_contribution;
{
Skybuck's GitFlow
version 0.08 created on 29 august 2025 by Skybuck Flying and Gemini (AI) and Co-Pilot (AI).
credits:
Almost all code by Google Gemini 2.5 Pro.
GetBranchVersionDigits code by Microsoft Co-Pilot.
Software Idea and Prompting and Overwatching the AI: Skybuck Flying.
improvements for version 0.08:
+ local git support
+ better contribution number
Delphi code developed for Delphi 12.3 and Windows 11.
}
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
System.RegularExpressions,
System.IOUtils,
Winapi.Windows,
ActiveX,
MSXML;
function ExecuteCommand( const ParaCommand : string; out ParaOutput : TStringList ) : Integer;
var
vSA : TSecurityAttributes;
vSI : TStartupInfo;
vPI : TProcessInformation;
vhRead, vhWrite : THandle;
vBuffer : array[0..255] of AnsiChar;
vBytesRead : DWord;
vCmd : string;
begin
ParaOutput := TStringList.Create;
Result := -1;
vSA.nLength := SizeOf(TSecurityAttributes);
vSA.bInheritHandle := True;
vSA.lpSecurityDescriptor := nil;
if not CreatePipe(vhRead, vhWrite, @vSA, 0) then
begin
Exit;
end;
FillChar(vSI, SizeOf(TStartupInfo), 0);
vSI.cb := SizeOf(TStartupInfo);
vSI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
vSI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
vSI.hStdOutput := vhWrite;
vSI.hStdError := vhWrite;
vSI.wShowWindow := SW_HIDE;
vCmd := 'cmd.exe /C ' + ParaCommand;
if not CreateProcess(nil, PChar(vCmd), nil, nil, True, 0, nil, nil, vSI, vPI) then
begin
CloseHandle(vhRead);
CloseHandle(vhWrite);
Exit;
end;
CloseHandle(vhWrite);
while True do
begin
if not ReadFile(vhRead, vBuffer, SizeOf(vBuffer) - 1, vBytesRead, nil) or (vBytesRead = 0) then
begin
break;
end;
vBuffer[vBytesRead] := #0;
ParaOutput.Add(string(vBuffer));
end;
WaitForSingleObject(vPI.hProcess, INFINITE);
GetExitCodeProcess(vPI.hProcess, Cardinal(Result));
CloseHandle(vhRead);
CloseHandle(vPI.hProcess);
CloseHandle(vPI.hThread);
end;
function GetBranchVersionDigits: Integer;
var
XMLDoc: IXMLDOMDocument2;
Node: IXMLDOMNode;
ConfigPath: string;
CoInitResult: HRESULT;
begin
Result := 4; // Default value
ConfigPath := ExtractFilePath(ParamStr(0)) + 'SkybuckGitflow.cfg';
if FileExists(ConfigPath) then
begin
// Initialize COM for this thread
CoInitResult := CoInitialize(nil);
try
try
XMLDoc := CoDOMDocument60.Create;
if not Assigned(XMLDoc) then
begin
raise Exception.Create('Failed to create MSXML 6.0 document');
end;
XMLDoc.async := False;
if not XMLDoc.load(ConfigPath) then
begin
// Check for a parse error object before accessing its properties
if Assigned(XMLDoc.parseError) then
begin
raise Exception.Create('XML load failed: ' + XMLDoc.parseError.reason)
end
else
begin
raise Exception.Create('XML load failed with an unknown error.');
end;
end;
Node := XMLDoc.selectSingleNode('//BranchVersionDigits');
if Assigned(Node) then
begin
Result := Abs(StrToIntDef(Node.text, 4));
end;
except
on E: Exception do
begin
Writeln('Error processing config file: ', E.Message);
end;
end;
finally
// *** THE FIX IS HERE ***
// Release COM objects BEFORE CoUninitialize is called.
Node := nil;
XMLDoc := nil;
// Uninitialize COM only if it was successfully initialized on this call.
if SUCCEEDED(CoInitResult) then // Use SUCCEEDED for robustness
begin
CoUninitialize;
end;
end;
end;
end;
function RemoteOriginExists: boolean;
var
Output: TStringList;
begin
Output := TStringList.Create;
try
Result := ExecuteCommand('git remote get-url origin > NUL 2>&1', Output) = 0;
finally
Output.Free;
end;
end;
function GetGitConfigValue( const ParaConfigKey : string ) : string;
var
vOutput : TStringList;
begin
Result := '';
vOutput := TStringList.Create;
try
if ExecuteCommand('git config ' + ParaConfigKey, vOutput) = 0 then
begin
if vOutput.Count > 0 then
begin
Result := Trim(vOutput.Text);
end;
end;
finally
vOutput.Free;
end;
end;
function Slugify( const ParaInput : string ) : string;
begin
Result := ParaInput.ToLower;
Result := TRegEx.Replace(Result, '[^a-z0-9]+', '-');
Result := TRegEx.Replace(Result, '^-+|-+$', '');
if Length(Result) > 50 then
begin
Result := Copy(Result, 1, 50);
end;
end;
function GetNextContributionNumber( const ParaUserPrefix : string; ParaRemoteExists: boolean ) : Integer;
var
vOutput : TStringList;
vMaxNum : Integer;
vMatch : TMatch;
vNum : Integer;
vS, vRefs: string;
vRegex: TRegEx;
begin
vMaxNum := 0;
vOutput := TStringList.Create;
try
if ParaRemoteExists then
begin
ExecuteCommand('git fetch origin --prune', vOutput); // Sync with remote
vOutput.Clear;
vRefs := 'refs/heads refs/remotes/origin';
end
else
begin
vRefs := 'refs/heads';
end;
if ExecuteCommand('git for-each-ref --format="%(refname:short)" ' + vRefs, vOutput) = 0 then
begin
vS := vOutput.Text;
vRegex := TRegEx.Create('^' + ParaUserPrefix + 'Contribution(\d+)-', [roMultiLine]);
for vMatch in vRegex.Matches(vS) do
begin
if vMatch.Success then
begin
vNum := StrToIntDef(vMatch.Groups[1].Value, 0);
if vNum > vMaxNum then
begin
vMaxNum := vNum;
end;
end;
end;
end;
finally
vOutput.Free;
end;
Result := vMaxNum + 1;
end;
var
vUserPrefix, vDescription, vSlug, vNewBranchName, vFormatStr : string;
vNextNum, vBranchVersionDigits : Integer;
vOutput : TStringList;
vRemoteExists: Boolean;
begin
try
vBranchVersionDigits := GetBranchVersionDigits;
if ParamCount = 1 then
begin
vDescription := ParamStr(1);
vUserPrefix := '';
end
else if ParamCount >= 2 then
begin
vUserPrefix := ParamStr(1);
vDescription := ParamStr(2);
end
else
begin
Writeln('Usage: git-new-contribution [<UserPrefix>] "<Description/Goal...>"');
ExitCode := 1;
Exit;
end;
if vUserPrefix = '' then
begin
vUserPrefix := GetGitConfigValue('user.contributionPrefix');
if vUserPrefix = '' then
begin
vUserPrefix := GetGitConfigValue('user.name');
if vUserPrefix <> '' then
begin
vUserPrefix := TRegEx.Replace(vUserPrefix, '[^a-zA-Z0-9]', '');
end
else
begin
Writeln('Error: User prefix not provided and not found in git config.');
ExitCode := 1;
Exit;
end;
end;
end;
vSlug := Slugify(vDescription);
if vSlug = '' then
begin
Writeln('Error: Description resulted in empty slug.');
ExitCode := 1;
Exit;
end;
vOutput := TStringList.Create;
try
vRemoteExists := RemoteOriginExists;
Writeln('Switching to master branch...');
if ExecuteCommand('git checkout master', vOutput) <> 0 then
begin
Writeln('Error: Failed to checkout master.');
Writeln(vOutput.Text);
ExitCode := 1;
Exit;
end;
vOutput.Clear;
if vRemoteExists then
begin
Writeln('Fetching latest master...');
if ExecuteCommand('git pull origin master', vOutput) <> 0 then
begin
Writeln('Warning: Failed to pull latest master. Proceeding with local master.');
Writeln(vOutput.Text);
end;
vOutput.Clear;
end;
vNextNum := GetNextContributionNumber(vUserPrefix, vRemoteExists);
vFormatStr := Format('%%sContribution%%0.%dd-%%s', [vBranchVersionDigits]);
vNewBranchName := Format(vFormatStr, [vUserPrefix, vNextNum, vSlug]);
if ExecuteCommand('git show-ref --verify refs/heads/' + vNewBranchName, vOutput) = 0 then
begin
Writeln('Error: Local branch already exists.');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
Writeln('Creating new branch: ' + vNewBranchName);
if ExecuteCommand('git checkout -b ' + vNewBranchName + ' master', vOutput) <> 0 then
begin
Writeln('Error: Failed to create local branch.');
Writeln(vOutput.Text);
ExitCode := 1;
Exit;
end;
vOutput.Clear;
if vRemoteExists then
begin
Writeln('Pushing new branch to origin...');
if ExecuteCommand('git push -u origin ' + vNewBranchName, vOutput) <> 0 then
begin
Writeln('Error: Failed to push new branch.');
Writeln(vOutput.Text);
ExitCode := 1;
Exit;
end;
vOutput.Clear;
end;
if ExecuteCommand('cmd.exe /c "' + ExtractFilePath(ParamStr(0)) + 'git-set-active.exe" ' + vNewBranchName, vOutput) <> 0 then
begin
Writeln('Warning: Failed to mark branch active.');
Writeln(vOutput.Text);
end;
vOutput.Clear;
Writeln('');
Writeln('Successfully created and activated new contribution branch:');
Writeln('-> **' + vNewBranchName + '**');
Writeln('You are now on this branch. Start coding!');
finally
vOutput.Free;
end;
except
on E : Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ExitCode := 1;
end;
end;
end.
Save program 3 as "git-set-active.dpr":
program git_set_active;
{
Skybuck's GitFlow
version 0.08 created on 29 august 2025 by Skybuck Flying and Gemini (AI) and Co-Pilot (AI).
credits:
Almost all code by Google Gemini 2.5 Pro.
GetBranchVersionDigits code by Microsoft Co-Pilot.
Software Idea and Prompting and Overwatching the AI: Skybuck Flying.
improvements for version 0.08:
+ local git support
+ better contribution number
Delphi code developed for Delphi 12.3 and Windows 11.
}
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
System.IOUtils,
Winapi.Windows;
function ExecuteCommand(const Command: string; out Output: TStringList): Integer;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
hRead, hWrite: THandle;
Buffer: array[0..1023] of AnsiChar;
BytesRead: DWord;
Cmd: string;
FullOutput: AnsiString;
begin
Output := TStringList.Create;
Result := -1;
FullOutput := '';
SA.nLength := SizeOf(TSecurityAttributes);
SA.bInheritHandle := True;
SA.lpSecurityDescriptor := nil;
if not CreatePipe(hRead, hWrite, @SA, 0) then
begin
Exit;
end;
try
FillChar(SI, SizeOf(TStartupInfo), 0);
SI.cb := SizeOf(TStartupInfo);
SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
SI.hStdOutput := hWrite;
SI.hStdError := hWrite;
SI.wShowWindow := SW_HIDE;
Cmd := 'cmd.exe /C ' + Command;
if not CreateProcess(nil, PChar(Cmd), nil, nil, True, 0, nil, nil, SI, PI) then
begin
Exit;
end;
CloseHandle(hWrite);
try
while True do
begin
if not ReadFile(hRead, Buffer, SizeOf(Buffer) - 1, BytesRead, nil) or (BytesRead = 0) then
begin
break;
end;
Buffer[BytesRead] := #0;
FullOutput := FullOutput + AnsiString(Buffer);
end;
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, Cardinal(Result));
finally
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end;
finally
CloseHandle(hRead);
end;
Output.Text := string(FullOutput);
end;
function RemoteOriginExists: boolean;
var
Output: TStringList;
begin
Output := TStringList.Create;
try
Result := ExecuteCommand('git remote get-url origin > NUL 2>&1', Output) = 0;
finally
Output.Free;
end;
end;
function BranchExists(const ParaBranchName: string; ParaRemoteExists: boolean): boolean;
var
vOutput: TStringList;
begin
Result := False;
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/heads/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
Exit;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git show-ref --verify "refs/remotes/origin/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
end;
end;
finally
vOutput.Free;
end;
end;
function GetBranchHash(const ParaBranchName: string; ParaRemoteExists: boolean): string;
var
vOutput: TStringList;
begin
Result := '';
vOutput := TStringList.Create;
try
if ParaRemoteExists then
begin
if ExecuteCommand('git rev-parse "refs/remotes/origin/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
if Result <> '' then
begin
Exit;
end;
end;
end;
vOutput.Clear;
if ExecuteCommand('git rev-parse "refs/heads/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end;
finally
vOutput.Free;
end;
end;
procedure DeleteTagIfExists(const ParaTagName: string; ParaRemoteExists: boolean);
var
vOutput: TStringList;
begin
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Writeln('Removing existing local tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git tag -d "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete local tag ' + ParaTagName + '.');
end;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git ls-remote --tags origin "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
if vOutput.Text <> '' then
begin
Writeln('Removing existing remote tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git push origin --delete "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete remote tag ' + ParaTagName + '.');
end;
end;
end;
end;
finally
vOutput.Free;
end;
end;
var
vBranchName, vActiveTag, vBranchHash: string;
vOutput: TStringList;
vRemoteExists: Boolean;
begin
try
if ParamCount <> 1 then
begin
Writeln('Usage: git-set-active <branchname>');
Writeln('Example: git-set-active SkybuckContribution001-ImplementLogin');
ExitCode := 1;
Exit;
end;
vBranchName := ParamStr(1);
vActiveTag := 'active/' + vBranchName;
vRemoteExists := RemoteOriginExists;
if not BranchExists(vBranchName, vRemoteExists) then
begin
Writeln('Error: Branch ''' + vBranchName + ''' not found locally or remotely.');
ExitCode := 1;
Exit;
end;
vBranchHash := GetBranchHash(vBranchName, vRemoteExists);
if vBranchHash = '' then
begin
Writeln('Error: Unable to determine commit hash for branch ''' + vBranchName + '''.');
ExitCode := 1;
Exit;
end;
DeleteTagIfExists('merged/' + vBranchName, vRemoteExists);
DeleteTagIfExists('rejected/' + vBranchName, vRemoteExists);
Writeln('Creating active tag: ' + vActiveTag);
vOutput := TStringList.Create;
try
if ExecuteCommand('git tag -f "' + vActiveTag + '" "' + vBranchHash + '"', vOutput) <> 0 then
begin
Writeln('Error: Failed to create tag ' + vActiveTag);
ExitCode := 1;
Exit;
end;
vOutput.Clear;
if vRemoteExists then
begin
Writeln('Pushing active tag to origin...');
if ExecuteCommand('git push -f origin "' + vActiveTag + '"', vOutput) <> 0 then
begin
Writeln('Error: Failed to push tag ' + vActiveTag + ' to origin');
ExitCode := 1;
Exit;
end;
end;
finally
vOutput.Free;
end;
Writeln('');
Writeln('Branch ' + vBranchName + ' is now marked as ACTIVE.');
Writeln('To view active branches: git tag --list "active/*"');
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ExitCode := 1;
end;
end;
end.
Save program 4 as "git-set-merged.dpr":
program git_set_merged;
{
Skybuck's GitFlow
version 0.08 created on 29 august 2025 by Skybuck Flying and Gemini (AI) and Co-Pilot (AI).
credits:
Almost all code by Google Gemini 2.5 Pro.
GetBranchVersionDigits code by Microsoft Co-Pilot.
Software Idea and Prompting and Overwatching the AI: Skybuck Flying.
improvements for version 0.08:
+ local git support
+ better contribution number
Delphi code developed for Delphi 12.3 and Windows 11.
}
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
System.IOUtils,
Winapi.Windows;
function ExecuteCommand(const Command: string; out Output: TStringList): Integer;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
hRead, hWrite: THandle;
Buffer: array[0..1023] of AnsiChar;
BytesRead: DWord;
Cmd: string;
FullOutput: AnsiString;
begin
Output := TStringList.Create;
Result := -1;
FullOutput := '';
SA.nLength := SizeOf(TSecurityAttributes);
SA.bInheritHandle := True;
SA.lpSecurityDescriptor := nil;
if not CreatePipe(hRead, hWrite, @SA, 0) then
begin
Exit;
end;
try
FillChar(SI, SizeOf(TStartupInfo), 0);
SI.cb := SizeOf(TStartupInfo);
SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
SI.hStdOutput := hWrite;
SI.hStdError := hWrite;
SI.wShowWindow := SW_HIDE;
Cmd := 'cmd.exe /C ' + Command;
if not CreateProcess(nil, PChar(Cmd), nil, nil, True, 0, nil, nil, SI, PI) then
begin
Exit;
end;
CloseHandle(hWrite);
try
while True do
begin
if not ReadFile(hRead, Buffer, SizeOf(Buffer) - 1, BytesRead, nil) or (BytesRead = 0) then
begin
break;
end;
Buffer[BytesRead] := #0;
FullOutput := FullOutput + AnsiString(Buffer);
end;
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, Cardinal(Result));
finally
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end;
finally
CloseHandle(hRead);
end;
Output.Text := string(FullOutput);
end;
function RemoteOriginExists: boolean;
var
Output: TStringList;
begin
Output := TStringList.Create;
try
Result := ExecuteCommand('git remote get-url origin > NUL 2>&1', Output) = 0;
finally
Output.Free;
end;
end;
function BranchExists(const ParaBranchName: string; ParaRemoteExists: boolean): boolean;
var
vOutput: TStringList;
begin
Result := False;
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/heads/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
Exit;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git show-ref --verify "refs/remotes/origin/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
end;
end;
finally
vOutput.Free;
end;
end;
function GetBranchHash(const ParaBranchName: string; ParaRemoteExists: boolean): string;
var
vOutput: TStringList;
begin
Result := '';
vOutput := TStringList.Create;
try
if ParaRemoteExists then
begin
if ExecuteCommand('git rev-parse "refs/remotes/origin/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
if Result <> '' then
begin
Exit;
end;
end;
end;
vOutput.Clear;
if ExecuteCommand('git rev-parse "refs/heads/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end;
finally
vOutput.Free;
end;
end;
procedure DeleteTagIfExists(const ParaTagName: string; ParaRemoteExists: boolean);
var
vOutput: TStringList;
begin
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Writeln('Removing existing local tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git tag -d "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete local tag ' + ParaTagName + '.');
end;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git ls-remote --tags origin "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
if vOutput.Text <> '' then
begin
Writeln('Removing existing remote tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git push origin --delete "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete remote tag ' + ParaTagName + '.');
end;
end;
end;
end;
finally
vOutput.Free;
end;
end;
var
vBranchName, vMergedTag, vBranchHash: string;
vOutput: TStringList;
vRemoteExists: Boolean;
begin
try
if ParamCount <> 1 then
begin
Writeln('Usage: git-set-merged <branchname>');
Writeln('Example: git-set-merged SkybuckContribution001-MyFeature');
ExitCode := 1;
Exit;
end;
vBranchName := ParamStr(1);
vMergedTag := 'merged/' + vBranchName;
vRemoteExists := RemoteOriginExists;
if not BranchExists(vBranchName, vRemoteExists) then
begin
Writeln('Error: Branch ''' + vBranchName + ''' does not exist locally or remotely.');
ExitCode := 1;
Exit;
end;
vBranchHash := GetBranchHash(vBranchName, vRemoteExists);
if vBranchHash = '' then
begin
Writeln('Error: Unable to determine commit hash for branch ''' + vBranchName + '''.');
ExitCode := 1;
Exit;
end;
DeleteTagIfExists('active/' + vBranchName, vRemoteExists);
DeleteTagIfExists('rejected/' + vBranchName, vRemoteExists);
Writeln('Creating merged tag: ' + vMergedTag);
vOutput := TStringList.Create;
try
if ExecuteCommand('git tag -f "' + vMergedTag + '" "' + vBranchHash + '"', vOutput) <> 0 then
begin
Writeln('Error: Failed to create tag ' + vMergedTag + '.');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
if vRemoteExists then
begin
Writeln('Pushing merged tag to origin...');
if ExecuteCommand('git push -f origin "' + vMergedTag + '"', vOutput) <> 0 then
begin
Writeln('Error: Failed to push tag ' + vMergedTag + ' to origin.');
ExitCode := 1;
Exit;
end;
end;
finally
vOutput.Free;
end;
Writeln('');
Writeln('Branch ' + vBranchName + ' successfully marked as MERGED.');
Writeln('It remains in your repository history.');
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ExitCode := 1;
end;
end;
end.
Save program 5 as "git-set-rejected.dpr":
program git_set_rejected;
{
Skybuck's GitFlow
version 0.08 created on 29 august 2025 by Skybuck Flying and Gemini (AI) and Co-Pilot (AI).
credits:
Almost all code by Google Gemini 2.5 Pro.
GetBranchVersionDigits code by Microsoft Co-Pilot.
Software Idea and Prompting and Overwatching the AI: Skybuck Flying.
improvements for version 0.08:
+ local git support
+ better contribution number
Delphi code developed for Delphi 12.3 and Windows 11.
}
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
System.IOUtils,
Winapi.Windows;
function ExecuteCommand(const Command: string; out Output: TStringList): Integer;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
hRead, hWrite: THandle;
Buffer: array[0..1023] of AnsiChar;
BytesRead: DWord;
Cmd: string;
FullOutput: AnsiString;
begin
Output := TStringList.Create;
Result := -1;
FullOutput := '';
SA.nLength := SizeOf(TSecurityAttributes);
SA.bInheritHandle := True;
SA.lpSecurityDescriptor := nil;
if not CreatePipe(hRead, hWrite, @SA, 0) then
begin
Exit;
end;
try
FillChar(SI, SizeOf(TStartupInfo), 0);
SI.cb := SizeOf(TStartupInfo);
SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
SI.hStdOutput := hWrite;
SI.hStdError := hWrite;
SI.wShowWindow := SW_HIDE;
Cmd := 'cmd.exe /C ' + Command;
if not CreateProcess(nil, PChar(Cmd), nil, nil, True, 0, nil, nil, SI, PI) then
begin
Exit;
end;
CloseHandle(hWrite);
try
while True do
begin
if not ReadFile(hRead, Buffer, SizeOf(Buffer) - 1, BytesRead, nil) or (BytesRead = 0) then
begin
break;
end;
Buffer[BytesRead] := #0;
FullOutput := FullOutput + AnsiString(Buffer);
end;
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, Cardinal(Result));
finally
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end;
finally
CloseHandle(hRead);
end;
Output.Text := string(FullOutput);
end;
function RemoteOriginExists: boolean;
var
Output: TStringList;
begin
Output := TStringList.Create;
try
Result := ExecuteCommand('git remote get-url origin > NUL 2>&1', Output) = 0;
finally
Output.Free;
end;
end;
function BranchExists(const ParaBranchName: string; ParaRemoteExists: boolean): boolean;
var
vOutput: TStringList;
begin
Result := False;
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/heads/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
Exit;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git show-ref --verify "refs/remotes/origin/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
end;
end;
finally
vOutput.Free;
end;
end;
function GetBranchHash(const ParaBranchName: string; ParaRemoteExists: boolean): string;
var
vOutput: TStringList;
begin
Result := '';
vOutput := TStringList.Create;
try
if ParaRemoteExists then
begin
if ExecuteCommand('git rev-parse "refs/remotes/origin/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
if Result <> '' then
begin
Exit;
end;
end;
end;
vOutput.Clear;
if ExecuteCommand('git rev-parse "refs/heads/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end;
finally
vOutput.Free;
end;
end;
procedure DeleteTagIfExists(const ParaTagName: string; ParaRemoteExists: boolean);
var
vOutput: TStringList;
begin
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Writeln('Removing existing local tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git tag -d "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete local tag ' + ParaTagName + '.');
end;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git ls-remote --tags origin "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
if vOutput.Text <> '' then
begin
Writeln('Removing existing remote tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git push origin --delete "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete remote tag ' + ParaTagName + '.');
end;
end;
end;
end;
finally
vOutput.Free;
end;
end;
var
vBranchName, vRejectedTag, vBranchHash: string;
vOutput: TStringList;
vRemoteExists: Boolean;
begin
try
if ParamCount <> 1 then
begin
Writeln('Usage: git-set-rejected <branchname>');
Writeln('Example: git-set-rejected AI0001Contribution002-ExperimentalAlgorithm');
ExitCode := 1;
Exit;
end;
vBranchName := ParamStr(1);
vRejectedTag := 'rejected/' + vBranchName;
vRemoteExists := RemoteOriginExists;
if not BranchExists(vBranchName, vRemoteExists) then
begin
Writeln('Error: Branch ''' + vBranchName + ''' does not exist locally or remotely.');
ExitCode := 1;
Exit;
end;
vBranchHash := GetBranchHash(vBranchName, vRemoteExists);
if vBranchHash = '' then
begin
Writeln('Error: Could not determine commit hash for branch ''' + vBranchName + '''.');
ExitCode := 1;
Exit;
end;
DeleteTagIfExists('active/' + vBranchName, vRemoteExists);
DeleteTagIfExists('merged/' + vBranchName, vRemoteExists);
Writeln('Creating rejected tag: ' + vRejectedTag);
vOutput := TStringList.Create;
try
if ExecuteCommand('git tag -f "' + vRejectedTag + '" "' + vBranchHash + '"', vOutput) <> 0 then
begin
Writeln('Error: Could not create tag ''' + vRejectedTag + '''');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
if vRemoteExists then
begin
Writeln('Pushing rejected tag to origin...');
if ExecuteCommand('git push -f origin "' + vRejectedTag + '"', vOutput) <> 0 then
begin
Writeln('Error: Could not push tag ''' + vRejectedTag + ''' to origin');
ExitCode := 1;
Exit;
end;
end;
finally
vOutput.Free;
end;
Writeln('');
Writeln('Branch ' + vBranchName + ' marked as REJECTED.');
Writeln('Tag ''' + vRejectedTag + ''' added for reference.');
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ExitCode := 1;
end;
end;
end.
Save program 6 as "git-set-revive.dpr":
program git_set_revive;
{
Skybuck's GitFlow
version 0.08 created on 29 august 2025 by Skybuck Flying and Gemini (AI) and Co-Pilot (AI).
credits:
Almost all code by Google Gemini 2.5 Pro.
GetBranchVersionDigits code by Microsoft Co-Pilot.
Software Idea and Prompting and Overwatching the AI: Skybuck Flying.
improvements for version 0.08:
+ local git support
+ better contribution number
Delphi code developed for Delphi 12.3 and Windows 11.
}
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
System.IOUtils,
Winapi.Windows;
function ExecuteCommand(const Command: string; out Output: TStringList): Integer;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
hRead, hWrite: THandle;
Buffer: array[0..1023] of AnsiChar;
BytesRead: DWord;
Cmd: string;
FullOutput: AnsiString;
begin
Output := TStringList.Create;
Result := -1;
FullOutput := '';
SA.nLength := SizeOf(TSecurityAttributes);
SA.bInheritHandle := True;
SA.lpSecurityDescriptor := nil;
if not CreatePipe(hRead, hWrite, @SA, 0) then
begin
Exit;
end;
try
FillChar(SI, SizeOf(TStartupInfo), 0);
SI.cb := SizeOf(TStartupInfo);
SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
SI.hStdOutput := hWrite;
SI.hStdError := hWrite;
SI.wShowWindow := SW_HIDE;
Cmd := 'cmd.exe /C ' + Command;
if not CreateProcess(nil, PChar(Cmd), nil, nil, True, 0, nil, nil, SI, PI) then
begin
Exit;
end;
CloseHandle(hWrite);
try
while True do
begin
if not ReadFile(hRead, Buffer, SizeOf(Buffer) - 1, BytesRead, nil) or (BytesRead = 0) then
begin
break;
end;
Buffer[BytesRead] := #0;
FullOutput := FullOutput + AnsiString(Buffer);
end;
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, Cardinal(Result));
finally
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end;
finally
CloseHandle(hRead);
end;
Output.Text := string(FullOutput);
end;
function RemoteOriginExists: boolean;
var
Output: TStringList;
begin
Output := TStringList.Create;
try
Result := ExecuteCommand('git remote get-url origin > NUL 2>&1', Output) = 0;
finally
Output.Free;
end;
end;
function BranchExists(const ParaBranchName: string; ParaRemoteExists: boolean): boolean;
var
vOutput: TStringList;
begin
Result := False;
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/heads/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
Exit;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git show-ref --verify "refs/remotes/origin/' + ParaBranchName + '"', vOutput) = 0 then
begin
Result := True;
end;
end;
finally
vOutput.Free;
end;
end;
function HasTag(const ParaTagName: string; ParaRemoteExists: boolean): boolean;
var
vOutput: TStringList;
begin
Result := False;
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Result := True;
Exit;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git ls-remote --tags origin "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Result := vOutput.Text <> '';
end;
end;
finally
vOutput.Free;
end;
end;
procedure DeleteTagIfExists(const ParaTagName: string; ParaRemoteExists: boolean);
var
vOutput: TStringList;
begin
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Writeln('Removing existing local tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git tag -d "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete local tag ' + ParaTagName + '.');
end;
end;
if ParaRemoteExists then
begin
vOutput.Clear;
if ExecuteCommand('git ls-remote --tags origin "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
if vOutput.Text <> '' then
begin
Writeln('Removing existing remote tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git push origin --delete "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete remote tag ' + ParaTagName + '.');
end;
end;
end;
end;
finally
vOutput.Free;
end;
end;
var
vBranchName: string;
vHasTag: boolean;
vOutput: TStringList;
vRemoteExists: Boolean;
begin
try
if ParamCount <> 1 then
begin
Writeln('Usage: git-set-revive <branchname>');
Writeln('Example: git-set-revive SkybuckContribution005-BugfixRethink');
ExitCode := 1;
Exit;
end;
vBranchName := ParamStr(1);
vRemoteExists := RemoteOriginExists;
if not BranchExists(vBranchName, vRemoteExists) then
begin
Writeln('Error: Branch ''' + vBranchName + ''' not found locally or remotely.');
ExitCode := 1;
Exit;
end;
vHasTag := HasTag('merged/' + vBranchName, vRemoteExists) or HasTag('rejected/' + vBranchName, vRemoteExists);
if not vHasTag then
begin
Writeln('Error: Branch ''' + vBranchName + ''' is not marked as merged or rejected.');
Writeln('If it''s active, run: git-set-active ' + vBranchName);
ExitCode := 1;
Exit;
end;
Writeln('Attempting to revive branch ''' + vBranchName + '''...');
DeleteTagIfExists('merged/' + vBranchName, vRemoteExists);
DeleteTagIfExists('rejected/' + vBranchName, vRemoteExists);
Writeln('---');
Writeln('Calling git-set-active to apply active tag...');
vOutput := TStringList.Create;
try
if ExecuteCommand('cmd.exe /c "' + ExtractFilePath(ParamStr(0)) + 'git-set-active.exe" ' + vBranchName, vOutput) <> 0 then
begin
Writeln(vOutput.Text);
Writeln('Error: git-set-active failed. Try running manually: git-set-active ' + vBranchName);
ExitCode := 1;
Exit;
end;
Writeln(vOutput.Text);
finally
vOutput.Free;
end;
Writeln('');
Writeln('Branch ' + vBranchName + ' successfully REVIVED and marked as ACTIVE.');
Writeln('This does not rebase history onto master.');
Writeln('To switch to it: git checkout ' + vBranchName);
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ExitCode := 1;
end;
end;
end.
Save program 7 as "git-the-future.dpr":
program git_the_future;
{
Skybuck's GitFlow
version 0.08 created on 29 august 2025 by Skybuck Flying and Gemini (AI) and Co-Pilot (AI).
credits:
Almost all code by Google Gemini 2.5 Pro.
GetBranchVersionDigits code by Microsoft Co-Pilot.
Software Idea and Prompting and Overwatching the AI: Skybuck Flying.
improvements for version 0.08:
+ local git support
+ better contribution number
Delphi code developed for Delphi 12.3 and Windows 11.
}
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
System.IOUtils,
Winapi.Windows;
function ExecuteCommand(const Command: string; out Output: TStringList; PassThrough: Boolean = False): Integer;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
hRead, hWrite: THandle;
Buffer: array[0..1023] of AnsiChar;
BytesRead: DWord;
Cmd: string;
FullOutput: AnsiString;
StdOut, StdErr: THandle;
begin
Output := TStringList.Create;
Result := -1;
FullOutput := '';
SA.nLength := SizeOf(TSecurityAttributes);
SA.bInheritHandle := True;
SA.lpSecurityDescriptor := nil;
if not CreatePipe(hRead, hWrite, @SA, 0) then
begin
Exit;
end;
try
FillChar(SI, SizeOf(TStartupInfo), 0);
SI.cb := SizeOf(TStartupInfo);
if PassThrough then
begin
StdOut := GetStdHandle(STD_OUTPUT_HANDLE);
StdErr := GetStdHandle(STD_ERROR_HANDLE);
SI.dwFlags := STARTF_USESTDHANDLES;
SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
SI.hStdOutput := StdOut;
SI.hStdError := StdErr;
end
else
begin
SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
SI.hStdOutput := hWrite;
SI.hStdError := hWrite;
SI.wShowWindow := SW_HIDE;
end;
Cmd := 'cmd.exe /C ' + Command;
if not CreateProcess(nil, PChar(Cmd), nil, nil, True, 0, nil, nil, SI, PI) then
begin
Exit;
end;
if not PassThrough then
begin
CloseHandle(hWrite);
end;
try
if not PassThrough then
begin
while True do
begin
if not ReadFile(hRead, Buffer, SizeOf(Buffer) - 1, BytesRead, nil) or (BytesRead = 0) then
begin
break;
end;
Buffer[BytesRead] := #0;
FullOutput := FullOutput + AnsiString(Buffer);
end;
end;
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, Cardinal(Result));
finally
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end;
finally
if not PassThrough then
begin
CloseHandle(hRead);
end;
end;
Output.Text := string(FullOutput);
end;
function RemoteOriginExists: boolean;
var
Output: TStringList;
begin
Output := TStringList.Create;
try
Result := ExecuteCommand('git remote get-url origin > NUL 2>&1', Output) = 0;
finally
Output.Free;
end;
end;
function GetCurrentBranch: string;
var
vOutput: TStringList;
begin
Result := '';
vOutput := TStringList.Create;
try
if ExecuteCommand('git rev-parse --abbrev-ref HEAD', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end;
finally
vOutput.Free;
end;
end;
var
vCurrentBranch: string;
vRebaseStatus: Integer;
vOutput: TStringList;
vRemoteExists: Boolean;
begin
try
vCurrentBranch := GetCurrentBranch;
if (vCurrentBranch = '') or (vCurrentBranch = 'HEAD') then
begin
Writeln('Error: You are not on a branch (detached HEAD). Checkout a branch first.');
ExitCode := 1;
Exit;
end;
if vCurrentBranch.ToLower = 'master' then
begin
Writeln('Error: You''re on ''master''. This command is meant for feature branches.');
ExitCode := 1;
Exit;
end;
Writeln('Preparing to rebase branch ''' + vCurrentBranch + ''' onto latest ''master''...');
vOutput := TStringList.Create;
try
vRemoteExists := RemoteOriginExists;
Writeln('Updating ''master''...');
if ExecuteCommand('git checkout master', vOutput) <> 0 then
begin
Writeln('Error: Could not checkout master.');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
if vRemoteExists then
begin
if ExecuteCommand('git pull origin master', vOutput) <> 0 then
begin
Writeln('Warning: Could not pull from origin master. Continuing with local master.');
end;
vOutput.Clear;
end;
if ExecuteCommand('git checkout "' + vCurrentBranch + '"', vOutput) <> 0 then
begin
Writeln('Error: Could not checkout back to ''' + vCurrentBranch + '''.');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
Writeln('');
Writeln('Starting rebase of ''' + vCurrentBranch + ''' onto ''master''...');
Writeln('----------------------------------------');
vRebaseStatus := ExecuteCommand('git rebase master', vOutput, True);
if vRebaseStatus = 0 then
begin
Writeln('----------------------------------------');
Writeln('Rebase completed successfully!');
Writeln('Your branch ''' + vCurrentBranch + ''' is now on top of master.');
if vRemoteExists then
begin
Writeln('To update remote:');
Writeln(' git push --force-with-lease origin ' + vCurrentBranch);
end;
end
else if vRebaseStatus = 1 then
begin
Writeln('----------------------------------------');
Writeln('Rebase paused due to conflicts.');
Writeln('Resolve conflicts manually, then run:');
Writeln(' git add .');
Writeln(' git rebase --continue');
Writeln('Or to abort:');
Writeln(' git rebase --abort');
ExitCode := 1;
end
else
begin
Writeln('----------------------------------------');
Writeln('Rebase failed with unexpected exit code: ' + IntToStr(vRebaseStatus));
ExitCode := 1;
end;
finally
vOutput.Free;
end;
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ExitCode := 1;
end;
end;
end.
Testing:
git-new-contribution has been tested and works ok.
git-set-active.exe is used by git-new-contribution seems to work ok.
The rest of the programs still need to be tested more rigorously/better, for now posting this update so it's more workable and testable (locally).
Bye for now,
Skybuck Flying.