Was "Re: [RFC] Proposed Git Workflow for Permanent History, Explicit Branch Status, and Developer Continuity" now "Skybuck's GitFlow"
- From
Skybuck Flying <skybuck2000@hotmail.com>
- Date
- Aug 29, 2025, 19:42 UTC
- Message-ID
- <VI1PR02MB42713B3BBD5802512B5FC9FBB33AA@VI1PR02MB4271.eurprd02.prod.outlook.com>
- In-Reply-To
- <DB7PR02MB4265527016FB04A500FBE321B35BA@DB7PR02MB4265.eurprd02.prod.outlook.com>
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.