Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance Git Commit Script for Improved Usability and Compatibility #28

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 135 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,147 @@
# greenhat <img src="https://github.com/4148/greenhat/blob/master/greenhat.png" alt="greenhat image" width="10%" height="10%"/>
greenhat is a quick hack for decorating your GitHub contribution calendar with commits for the past `n` days. It uses the `GIT_AUTHOR_DATE` and `GIT_COMMITTER_DATE` environmental variables to make commits appear in the past. Be warned that greenhat will clobber your repository's commit history.

### How to Use
Place `greenhat.py` in your Git repository. Make sure your [remote repository URL is set](https://help.github.com/articles/adding-a-remote/), and that you have a [public SSH key set up](https://help.github.com/articles/generating-ssh-keys/). Then run the script with the python interpreter, with an integer specifying `n` number of days before today to generate commits for. E.g.,
# GreenHat: Simulating Git Commit History

python greenhat.py <n>
**GreenHat** 是一个用于模拟 Git 提交记录的脚本工具,可以通过伪造指定天数内的提交记录来生成直观的 GitHub 提交图表(绿色格子)。支持设置从指定日期开始或结束的提交记录。

It might take a while to generate all the commits. If greenhat stops before it finishes, you can resume where you last left off by specifying a date before today when you want it to resume, like so:
---

python greenhat.py <n> <date>
## 功能概述

`n` is the remaining days you want to generate commits for, and `date` is a date string in the form `yyyy-mm-dd` (e.g., 2013-04-05).
- 模拟每天的多次提交记录。
- 支持自定义起始日期或结束日期。
- 自动生成提交历史并推送至远程仓库。
- 提交历史的时间戳包含本地时区信息。

#### An Example
---

The following calendar is the result of running `python greenhat.py 365`:
## 平台限制

<img src="https://github.com/4148/greenhat/blob/master/example.png" alt="example image"/>
1. **操作系统**
- 支持 **Windows**(使用 `cmd` 和 `set` 设置环境变量)。
- **Linux** 和 **MacOS** 用户需修改 `set` 命令为 `export`,脚本需做小幅调整。

The run took a total of eight hours. Beautiful, isn't it?
2. **Git 环境**
- 必须安装 Git。
- 当前目录必须是一个 Git 仓库,并且已配置远程仓库(运行 `git remote -v` 验证)。

Enjoy your decorated calendar!
3. **Python 版本**
- 支持 Python 3.6 及以上版本。

### License
greenhat is distributed under the GNU General Public License v3.0 (GPLv3).
4. **权限**
- 必须有对 Git 仓库的写入权限。

---

## 使用方法

### 1. 准备环境
- 安装 Python 和 Git,并确保它们已添加到系统 PATH。
- 初始化或克隆一个 Git 仓库:
```bash
git init
git remote add origin <远程仓库URL>
```
```bash
git clone <远程仓库URL>
```

### 2. 下载脚本
将代码保存为 `greenhat.py`。

### 3. 执行脚本
运行以下命令以生成提交记录:

#### 默认从今天开始,向前推 `n` 天生成提交记录
```bash
python greenhat.py 365
```

#### 指定起始日期,向前推 `n` 天生成提交记录
```bash
python greenhat.py 365 2024-01-01
```

#### 指定起始日期,向后推 `n` 天生成提交记录(需要修改代码逻辑)
如需向后推提交记录,请使用调整后的脚本(见上一节),运行如下命令:
```bash
python greenhat.py 100 2024-01-01
```

### 4. 查看生成的提交记录
使用以下命令查看提交日志:
```bash
git log --pretty=format:"%ad %s" --date=local
```

### 5. 推送至远程仓库
脚本默认会执行以下命令推送更改:
```bash
git push
```

---

## 注意事项

1. **时区问题**
脚本会动态检测本地时区并应用到提交记录中,请确保系统时区设置正确。

2. **文件冲突**
脚本生成的临时文件 `realwork.txt` 会被自动删除,请确保仓库中没有同名文件以避免冲突。

3. **安全性**
脚本通过 `subprocess` 调用系统命令,运行前请确保代码来源可靠,避免潜在安全风险。

4. **Git 仓库状态**
确保当前分支干净(无未提交的更改),以防止提交冲突。

---

## 示例

### 示例 1:默认从今天开始,生成 365 天的提交记录
运行:
```bash
python greenhat.py 365
```

输出(部分日志示例):
```text
Processing Day 0: Sun Dec 31 12:00:00 2024 +0800
Processing Day 1: Sat Dec 30 12:00:00 2024 +0800
...
Processing Day 364: Tue Jan 01 12:00:00 2023 +0800
```

### 示例 2:从指定日期开始,生成 100 天的提交记录
运行:
```bash
python greenhat.py 100 2023-01-01
```

---

## 已知问题

1. **Windows 平台**
使用 `cmd` 的 `set` 命令设置环境变量,无法直接在 Linux 和 MacOS 上运行。

2. **提交频率随机性**
每天的提交次数是随机的(1 到 10 次),可根据需求修改 `randint` 的范围。

3. **多用户环境**
如果同一仓库有多人提交,伪造的记录可能会影响真实提交历史。

---

## 修改记录

- **版本 1.0**: 初始发布,支持随机生成提交记录。
- **版本 1.1**: 修复了 Windows 环境变量设置的问题,支持动态检测时区。

---

## 授权协议

本项目基于 GNU General Public License v3.0 (GPLv3) 发布,详情请参阅项目 LICENSE 文件。
74 changes: 46 additions & 28 deletions greenhat.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,54 @@
# Copyright (c) 2015 Angus H. (4148)
# Distributed under the GNU General Public License v3.0 (GPLv3).

from datetime import date, timedelta
from random import randint
import sys
from datetime import date, timedelta, datetime
from random import randint
import subprocess
import os

# returns a date string for the date that is N days before STARTDATE
# 动态获取指定日期的格式化日期字符串,包含本地时区
def get_date_string(n, startdate):
d = startdate - timedelta(days=n)
rtn = d.strftime("%a %b %d %X %Y %z -0400")
return rtn
d = startdate - timedelta(days=n)
# 动态获取本地时区
local_timezone = datetime.now().astimezone().strftime("%z")
rtn = d.strftime(f"%a %b %d %X %Y {local_timezone}")
return rtn

# main app
# 主程序
def main(argv):
if len(argv) < 1 or len(argv) > 2:
print "Error: Bad input."
sys.exit(1)
n = int(argv[0])
if len(argv) == 1:
startdate = date.today()
if len(argv) == 2:
startdate = date(int(argv[1][0:4]), int(argv[1][5:7]), int(argv[1][8:10]))
i = 0
while i <= n:
curdate = get_date_string(i, startdate)
num_commits = randint(1, 10)
for commit in range(0, num_commits):
subprocess.call("echo '" + curdate + str(randint(0, 1000000)) +"' > realwork.txt; sync; git add realwork.txt; GIT_AUTHOR_DATE='" + curdate + "' GIT_COMMITTER_DATE='" + curdate + "' git commit -m 'update'", shell=True)
i += 1
subprocess.call("git rm realwork.txt; git commit -m 'delete'; git push;", shell=True)
if len(argv) < 1 or len(argv) > 2:
print("Error: Bad input.")
sys.exit(1)

# 获取输入参数
n = int(argv[0]) # 天数
if len(argv) == 1:
startdate = date.today()
if len(argv) == 2:
startdate = date(int(argv[1][0:4]), int(argv[1][5:7]), int(argv[1][8:10]))

i = 0
while i <= n:
# 获取当前日期
curdate = get_date_string(i, startdate)
# 随机生成当天的提交次数
num_commits = randint(1, 10)

for commit in range(num_commits):
# 生成一个文件,并添加到 git
subprocess.call(f"echo {curdate}{randint(0, 1000000)} > realwork.txt", shell=True)
subprocess.call("git add realwork.txt", shell=True)

# 设置 GIT_AUTHOR_DATE 和 GIT_COMMITTER_DATE 并提交
subprocess.call(
f'set GIT_AUTHOR_DATE="{curdate}" && set GIT_COMMITTER_DATE="{curdate}" && git commit -m "update"',
shell=True,
)

print(f"Processing Day {i}: {curdate}") # 调试输出
i += 1

# 删除临时文件并推送
subprocess.call("git rm realwork.txt", shell=True)
subprocess.call("git commit -m 'delete'", shell=True)
subprocess.call("git push", shell=True)

if __name__ == "__main__":
main(sys.argv[1:])
main(sys.argv[1:])