Re: [RFC] Proposed Git Workflow for Permanent History, Explicit Branch Status, and Developer Continuity
From: Skybuck Flying <hidden>
Date: 2025-07-27 03:04:48
Good News,
Skybuck's Git Workflow is now a reality:
Gemini 2.5 Pro was capable and able to write the necessary enhancements in Delphi 12.3 computer programs.
The source code for these enhancements will be posted below in this message.
(Batch files and Powershell script were also briefly tried by Co-Pilot and Gemini but proved to difficult to get working, so I didn't bother with it, cause it takes too much time to get working right but the AI and pretty quickly switched to Delphi, which Gemini is either very good at, or Delphi is just a cleaner language and/or more powerful, it's quite amazing how fast the AI was capable to complete these implementations programs by using the rapid prototyping language knows as Delphi !)
Here are the source codes for the tools. (The build perfectly, no errors, and they were briefly tested by the AI, the coming days I will probably test them further and will also be used by the AI, they should come in handy...)
Compiling/Building them is very easy:
Simply separate and store the raw text into file names as follows:
git-back-to.dpr
git-new-contribution.dpr
git-set-active.dpr
git-set-merged.dpr
git-set-rejected.dpr
git-set-revive.dpr
git-the-future.dpr
And then build them with either:
dcc32 <filename.dpr>
or
dcc64 <filename.dpr>
or
simply load them in the Delphi ide.
So example:
dcc64 git-back-to.dpr
dcc64 git-new-contribution.dpr
dcc64 git-set-active.dpr
dcc64 git-set-merged.dpr
dcc64 git-set-rejected.dpr
dcc64 git-set-revive.dpr
dcc64 git-the-future.dpr
This will produce 7 executables (for/tested on Windows 11 23h2):
git-back-to.exe
git-new-contribution.exe
git-set-active.exe
git-set-merged.exe
git-set-rejected.exe
git-set-revive.exe
git-the-future.exe
Then simply store these somewhere in a folder, setup the path environment variable to point to them, by adding a new line in windows and injecting the folder into it and click save/apply/ok, etc.
(git-set-active.exe is more or less an "internal" command, it's sometimes used by the other exe.)
Here is the source code for each one of them, (each program starts with "program" and ends with "end.")
program git_back_to;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
System.RegularExpressions,
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
Exit;
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
break;
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 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
Result := Trim(Output.Text);
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
Result := Copy(Result, 1, 50);
end;
function GetNextContributionNumber(const UserPrefix: string): Integer;
var
Output: TStringList;
MaxNum: Integer;
Match: TMatch;
Num: Integer;
S: string;
Regex: TRegEx;
begin
MaxNum := 0;
Output := TStringList.Create;
try
if ExecuteCommand('git for-each-ref --format="%(refname:short)" refs/heads refs/remotes/origin', Output) = 0 then
begin
S := Output.Text;
// The regex needs to be created with the user prefix
Regex := TRegEx.Create('^' + UserPrefix + 'Contribution(\d{3})-', [roMultiLine]);
for Match in Regex.Matches(S) do
begin
if Match.Success then
begin
Num := StrToIntDef(Match.Groups[1].Value, 0);
if Num > MaxNum then
MaxNum := Num;
end;
end;
end;
finally
Output.Free;
end;
Result := MaxNum + 1;
end;
function TagExists(const ParaTagName: string): 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;
end
else
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): 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;
end
else
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: string;
vNextNum: Integer;
vOutput: TStringList;
begin
try
// --- Input Validation ---
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);
// --- Configuration ---
vUserPrefix := GetGitConfigValue('user.contributionPrefix');
if vUserPrefix = '' then
begin
vUserPrefix := GetGitConfigValue('user.name');
if vUserPrefix <> '' then
begin
vUserPrefix := TRegEx.Replace(vUserPrefix, '[^a-zA-Z0-9]', '');
if Length(vUserPrefix) > 10 then
vUserPrefix := Copy(vUserPrefix, 1, 10);
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;
// --- Slugify Description ---
vSlug := Slugify(vDescription);
if vSlug = '' then
begin
Writeln('Error: Description resulted in empty slug.');
ExitCode := 1;
Exit;
end;
// --- Tag Existence Check ---
if not TagExists(vOldTagName) then
begin
Writeln('Error: Tag ''' + vOldTagName + ''' does not exist locally or remotely.');
ExitCode := 1;
Exit;
end;
// --- Determine Next Contribution Number ---
vNextNum := GetNextContributionNumber(vUserPrefix);
vNewBranchName := Format('%sContribution%0.3d-%s', [vUserPrefix, vNextNum, vSlug]);
// --- Check if branch already exists ---
if BranchExists(vNewBranchName) then
begin
Writeln('Error: Branch ''' + vNewBranchName + ''' already exists.');
ExitCode := 1;
Exit;
end;
vOutput := TStringList.Create;
try
// --- Create and Push Branch ---
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;
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;
// --- Activate Branch ---
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.
program git_new_contribution;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes,
System.RegularExpressions,
System.IOUtils,
Winapi.Windows;
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 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 ) : Integer;
var
vOutput : TStringList;
vMaxNum : Integer;
vMatch : TMatch;
vNum : Integer;
vS : string;
begin
vMaxNum := 0;
vOutput := TStringList.Create;
try
if ExecuteCommand('git for-each-ref --format="%(refname:short)" refs/heads refs/remotes/origin', vOutput) = 0 then
begin
vS := vOutput.Text;
for vMatch in TRegEx.Matches(vS, '^' + ParaUserPrefix + 'Contribution(\d{3})-') 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 : string;
vNextNum : Integer;
vOutput : TStringList;
begin
try
// --- Argument Parsing ---
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;
// --- Configuration ---
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]', '');
if Length(vUserPrefix) > 10 then
begin
vUserPrefix := Copy(vUserPrefix, 1, 10);
end;
end
else
begin
Writeln('Error: User prefix not provided and not found in git config.');
ExitCode := 1;
Exit;
end;
end;
end;
// --- Slugify Description ---
vSlug := Slugify(vDescription);
if vSlug = '' then
begin
Writeln('Error: Description resulted in empty slug.');
ExitCode := 1;
Exit;
end;
vOutput := TStringList.Create;
try
// --- Core Git Logic ---
Writeln('Fetching latest master and switching to it...');
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 ExecuteCommand('git pull origin master', vOutput) <> 0 then
begin
Writeln('Error: Failed to pull latest master.');
Writeln(vOutput.Text);
ExitCode := 1;
Exit;
end;
vOutput.Clear;
// --- Determine Next Contribution Number ---
vNextNum := GetNextContributionNumber(vUserPrefix);
vNewBranchName := Format('%sContribution%0.3d-%s', [vUserPrefix, vNextNum, vSlug]);
// --- Check if Branch Already Exists ---
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;
if ExecuteCommand('git show-ref --verify refs/remotes/origin/' + vNewBranchName, vOutput) = 0 then
begin
Writeln('Error: Remote branch already exists.');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
// --- Create and Push Branch ---
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 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;
// --- Set as Active ---
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.
program git_set_active;
{$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
Exit;
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); // Close the write end of the pipe in the parent process
try
while True do
begin
if not ReadFile(hRead, Buffer, SizeOf(Buffer) - 1, BytesRead, nil) or (BytesRead = 0) then
break;
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 BranchExists(const ParaBranchName: string): 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;
end
else
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): string;
var
vOutput: TStringList;
begin
Result := '';
vOutput := TStringList.Create;
try
if ExecuteCommand('git rev-parse "refs/remotes/origin/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end
else
begin
vOutput.Clear;
if ExecuteCommand('git rev-parse "refs/heads/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end;
end;
finally
vOutput.Free;
end;
end;
procedure DeleteTagIfExists(const ParaTagName: string);
var
vOutput: TStringList;
begin
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Writeln('Removing existing tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git push origin --delete "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete tag ' + ParaTagName + '.');
end;
end;
finally
vOutput.Free;
end;
end;
var
vBranchName, vActiveTag, vBranchHash: string;
vOutput: TStringList;
begin
try
// --- Input Validation ---
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;
// --- Check Branch Existence ---
if not BranchExists(vBranchName) then
begin
Writeln('Error: Branch ''' + vBranchName + ''' not found locally or remotely.');
ExitCode := 1;
Exit;
end;
// --- Determine Commit Hash ---
vBranchHash := GetBranchHash(vBranchName);
if vBranchHash = '' then
begin
Writeln('Error: Unable to determine commit hash for branch ''' + vBranchName + '''.');
ExitCode := 1;
Exit;
end;
// --- Clean Up Old Tags ---
DeleteTagIfExists('merged/' + vBranchName);
DeleteTagIfExists('rejected/' + vBranchName);
// --- Create and Push Active Tag ---
Writeln('Creating and pushing 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 ExecuteCommand('git push -f origin "' + vActiveTag + '"', vOutput) <> 0 then
begin
Writeln('Error: Failed to push tag ' + vActiveTag + ' to origin');
ExitCode := 1;
Exit;
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.
program git_set_merged;
{$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
Exit;
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
break;
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 BranchExists(const ParaBranchName: string): 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;
end
else
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): string;
var
vOutput: TStringList;
begin
Result := '';
vOutput := TStringList.Create;
try
if ExecuteCommand('git rev-parse "refs/remotes/origin/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end
else
begin
vOutput.Clear;
if ExecuteCommand('git rev-parse "refs/heads/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end;
end;
finally
vOutput.Free;
end;
end;
procedure DeleteTagIfExists(const ParaTagName: string);
var
vOutput: TStringList;
begin
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Writeln('Removing existing tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git push origin --delete "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Failed to delete tag ' + ParaTagName + '.');
end;
end;
finally
vOutput.Free;
end;
end;
var
vBranchName, vMergedTag, vBranchHash: string;
vOutput: TStringList;
begin
try
// --- Input Validation ---
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;
// --- Verify Branch Exists ---
if not BranchExists(vBranchName) then
begin
Writeln('Error: Branch ''' + vBranchName + ''' does not exist locally or remotely.');
ExitCode := 1;
Exit;
end;
// --- Get Latest Commit Hash ---
vBranchHash := GetBranchHash(vBranchName);
if vBranchHash = '' then
begin
Writeln('Error: Unable to determine commit hash for branch ''' + vBranchName + '''.');
ExitCode := 1;
Exit;
end;
// --- Remove active/rejected tags ---
DeleteTagIfExists('active/' + vBranchName);
DeleteTagIfExists('rejected/' + vBranchName);
// --- Create and Push Merged Tag ---
Writeln('Creating and pushing 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 ExecuteCommand('git push -f origin "' + vMergedTag + '"', vOutput) <> 0 then
begin
Writeln('Error: Failed to push tag ' + vMergedTag + ' to origin.');
ExitCode := 1;
Exit;
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.
program git_set_rejected;
{$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
Exit;
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
break;
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 BranchExists(const ParaBranchName: string): 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;
end
else
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): string;
var
vOutput: TStringList;
begin
Result := '';
vOutput := TStringList.Create;
try
if ExecuteCommand('git rev-parse "refs/remotes/origin/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end
else
begin
vOutput.Clear;
if ExecuteCommand('git rev-parse "refs/heads/' + ParaBranchName + '^{commit}"', vOutput) = 0 then
begin
Result := Trim(vOutput.Text);
end;
end;
finally
vOutput.Free;
end;
end;
procedure DeleteTagIfExists(const ParaTagName: string);
var
vOutput: TStringList;
begin
vOutput := TStringList.Create;
try
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Writeln('Removing remote tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git push origin --delete "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Could not delete tag ' + ParaTagName + '.');
end;
end;
finally
vOutput.Free;
end;
end;
var
vBranchName, vRejectedTag, vBranchHash: string;
vOutput: TStringList;
begin
try
// --- Input Validation ---
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;
// --- Branch Existence Check ---
if not BranchExists(vBranchName) then
begin
Writeln('Error: Branch ''' + vBranchName + ''' does not exist locally or remotely.');
ExitCode := 1;
Exit;
end;
// --- Commit Hash Resolution ---
vBranchHash := GetBranchHash(vBranchName);
if vBranchHash = '' then
begin
Writeln('Error: Could not determine commit hash for branch ''' + vBranchName + '''.');
ExitCode := 1;
Exit;
end;
// --- Remove active/merged tags ---
DeleteTagIfExists('active/' + vBranchName);
DeleteTagIfExists('merged/' + vBranchName);
// --- Create and Push Rejected Tag ---
Writeln('Creating and pushing 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 ExecuteCommand('git push -f origin "' + vRejectedTag + '"', vOutput) <> 0 then
begin
Writeln('Error: Could not push tag ''' + vRejectedTag + ''' to origin');
ExitCode := 1;
Exit;
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.
program git_set_revive;
{$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
Exit;
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
break;
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 BranchExists(const ParaBranchName: string): 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;
end
else
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): boolean;
var
vOutput: TStringList;
begin
Result := False;
vOutput := TStringList.Create;
try
if ExecuteCommand('git ls-remote --tags origin "' + ParaTagName + '"', vOutput) = 0 then
begin
Result := vOutput.Text <> '';
end;
finally
vOutput.Free;
end;
end;
procedure DeleteTagIfExists(const ParaTagName: string);
var
vOutput: TStringList;
begin
vOutput := TStringList.Create;
try
// Check remote tags first
if ExecuteCommand('git ls-remote --tags origin "' + ParaTagName + '"', vOutput) = 0 then
begin
if vOutput.Text <> '' then
begin
Writeln('Removing remote tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git push origin --delete "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Could not delete remote tag ' + ParaTagName + '.');
end;
end;
end;
// Check local tags
vOutput.Clear;
if ExecuteCommand('git show-ref --verify "refs/tags/' + ParaTagName + '"', vOutput) = 0 then
begin
Writeln('Removing local tag: ' + ParaTagName + '...');
vOutput.Clear;
if ExecuteCommand('git tag -d "' + ParaTagName + '"', vOutput) <> 0 then
begin
Writeln('Warning: Could not delete local tag ' + ParaTagName + '.');
end;
end;
finally
vOutput.Free;
end;
end;
var
vBranchName: string;
vHasTag: boolean;
vOutput: TStringList;
begin
try
// --- Input Validation ---
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);
// --- Check Branch Existence ---
if not BranchExists(vBranchName) then
begin
Writeln('Error: Branch ''' + vBranchName + ''' not found locally or remotely.');
ExitCode := 1;
Exit;
end;
// --- Check if it has merged or rejected tag remotely ---
vHasTag := HasTag('merged/' + vBranchName) or HasTag('rejected/' + vBranchName);
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 + '''...');
// --- Delete old tags ---
DeleteTagIfExists('merged/' + vBranchName);
DeleteTagIfExists('rejected/' + vBranchName);
// --- Mark as active by calling git-set-active ---
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.
program git_the_future;
{$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
Exit;
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
CloseHandle(hWrite);
try
if not PassThrough then
begin
while True do
begin
if not ReadFile(hRead, Buffer, SizeOf(Buffer) - 1, BytesRead, nil) or (BytesRead = 0) then
break;
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
CloseHandle(hRead);
end;
Output.Text := string(FullOutput);
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;
begin
try
// --- Determine current branch ---
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
// --- Update local master ---
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 ExecuteCommand('git pull origin master', vOutput) <> 0 then
begin
Writeln('Error: Could not pull from origin master.');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
// --- Return to original branch ---
if ExecuteCommand('git checkout "' + vCurrentBranch + '"', vOutput) <> 0 then
begin
Writeln('Error: Could not checkout back to ''' + vCurrentBranch + '''.');
ExitCode := 1;
Exit;
end;
vOutput.Clear;
// --- Begin rebase ---
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.');
Writeln('To update remote:');
Writeln(' git push --force-with-lease origin ' + vCurrentBranch);
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.
Bye for now,
Skybuck Flying
skybuck2000@hotmail.com