# by ChatGPT import curses import subprocess import sys def get_commits(filename): cmd = ['git', 'log', '--pretty=format:%h %ad %s', '--date=short', '--', filename] result = subprocess.run(cmd, capture_output=True, text=True) return result.stdout.splitlines() def get_file_at_commit(commit_hash, filename): cmd = ['git', 'show', f'{commit_hash}:{filename}'] result = subprocess.run(cmd, capture_output=True, text=True) return result.stdout.splitlines() def main(stdscr, filename): curses.curs_set(0) stdscr.keypad(True) commits = get_commits(filename) selected = 0 while True: stdscr.clear() height, width = stdscr.getmaxyx() mid = width // 2 # Draw commit list on the left for i, line in enumerate(commits): if i >= height: break if i == selected: stdscr.attron(curses.A_REVERSE) stdscr.addnstr(i, 0, line, mid - 1) if i == selected: stdscr.attroff(curses.A_REVERSE) # Show file content on the right if commits: commit_hash = commits[selected].split()[0] file_lines = get_file_at_commit(commit_hash, filename) for i, line in enumerate(file_lines): if i >= height: break stdscr.addnstr(i, mid + 1, line, width - mid - 2) stdscr.refresh() key = stdscr.getch() if key in [ord('q'), 27]: # q or ESC to quit break elif key in [curses.KEY_DOWN, ord('j')]: if selected < len(commits) - 1: selected += 1 elif key in [curses.KEY_UP, ord('k')]: if selected > 0: selected -= 1 if __name__ == "__main__": if len(sys.argv) != 2: print("Usage: python git_time_machine.py path/to/file") sys.exit(1) filename = sys.argv[1] curses.wrapper(main, filename)