Was "Re: [RFC] Proposed Git Workflow for Permanent History, Explicit Branch Status, and Developer Continuity" now "Skybuck's GitFlow"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.





[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux