#include <bits/stdc++.h>
using namespace std;
inline char gc() {
  static char now[1 << 16], *S, *T;
  if (T == S) {
    T = (S = now) + fread(now, 1, 1 << 16, stdin);
    if (T == S) return EOF;
  }
  return *S++;
}
inline long long read() {
  register long long x = 0, f = 1;
  char ch = gc();
  while (!isdigit(ch)) {
    if (ch == '-') f = -1;
    ch = gc();
  }
  while (isdigit(ch)) {
    x = (x << 3) + (x << 1) + ch - '0';
    ch = gc();
  }
  return (f == 1) ? x : -x;
}
struct LNB {
  int x[31];
  inline void insert(int y) {
    for (int i = 30; i >= 0; i--) {
      if ((y >> i) & 1LL) {
        if (!x[i]) return (void)(x[i] = y);
        y ^= x[i];
      }
    }
  }
  inline int getans(int y) {
    for (int i = 30; i >= 0; i--) {
      if ((x[i] ^ y) < y) y ^= x[i];
    }
    return y;
  }
} ori;
int sz[410021], F[410021], G[410021], sta[410021][3], top;
int find(int x) {
  if (x == F[x]) return x;
  return find(F[x]);
}
int getans(int x) {
  if (x == F[x]) return 0;
  return getans(F[x]) ^ G[x];
}
inline int merge(int x, int y, int z) {
  int xx = find(x), yy = find(y);
  z ^= getans(x) ^ getans(y);
  if (xx == yy) return z;
  if (sz[xx] > sz[yy]) swap(xx, yy);
  G[xx] = z;
  F[xx] = yy;
  sz[yy] += sz[xx];
  sta[++top][0] = yy, sta[top][1] = xx;
  return -1;
}
inline void cancel() {
  int u = sta[top][0], v = sta[top--][1];
  sz[u] -= sz[v];
  F[v] = v;
  G[v] = 0;
}
vector<pair<pair<int, int>, int> > seg[800001];
vector<int> Q[400101][3];
int ans[500005], n, m, st[500005], ecnt, All, T, qcnt;
int fin[500005], mque[500005][4], g[500005][3], q[500005][4];
void update(int rt, int lb, int rb, int l, int r, pair<pair<int, int>, int> x) {
  if (l > r) return;
  if (lb > r || rb < l) return;
  if (lb >= l && rb <= r) return (void)(seg[rt].push_back(x));
  update(rt << 1, lb, ((lb + rb) >> 1), l, r, x);
  update(rt << 1 | 1, ((lb + rb) >> 1) + 1, rb, l, r, x);
}
inline void Undo(int las) {
  for (; top != las;) cancel();
}
void solve(int rt, int lb, int rb, LNB X) {
  int las = top, Len = seg[rt].size();
  for (int i = 0; i < Len; i++) {
    int x = seg[rt][i].first.first, y = seg[rt][i].first.second,
        z = seg[rt][i].second;
    int op = merge(x, y, z);
    if (~op) X.insert(op);
  }
  if (lb == rb) {
    int qLen = Q[lb][0].size();
    for (int i = 0; i < qLen; i++) {
      int x = Q[lb][0][i], y = Q[lb][1][i], id = Q[lb][2][i];
      ans[id] = X.getans(getans(x) ^ getans(y));
    }
    Undo(las);
    return;
  }
  solve(rt << 1, lb, ((lb + rb) >> 1), X);
  solve(rt << 1 | 1, ((lb + rb) >> 1) + 1, rb, X);
  Undo(las);
}
map<pair<int, int>, int> has;
signed main() {
  n = read(), m = read();
  for (int i = 1; i <= n; i++) {
    F[i] = i, sz[i] = 1;
  }
  for (int i = 1; i <= m; i++) {
    g[i][0] = read(), g[i][1] = read(), g[i][2] = read();
  }
  T = read(), All = 1;
  for (int i = 1; i <= T; i++) {
    q[i][0] = read();
    q[i][1] = read();
    q[i][2] = read();
    if (q[i][0] == 1) q[i][3] = read();
    if (q[i][0] != 3) All++;
  }
  for (int i = 1; i <= m; i++) {
    st[++ecnt] = 1;
    fin[ecnt] = g[i][2];
    has[make_pair(g[i][0], g[i][1])] = ecnt;
  }
  int tim = 1;
  for (int i = 1; i <= T; i++) {
    if (q[i][0] == 1) {
      st[++ecnt] = ++tim;
      fin[ecnt] = q[i][3];
      has[make_pair(q[i][1], q[i][2])] = ecnt;
    } else if (q[i][0] == 2) {
      pair<int, int> P = make_pair(q[i][1], q[i][2]);
      int id = has[P];
      has[P] = 0;
      update(1, 1, All, st[id], tim++, make_pair(P, fin[id]));
    } else if (q[i][0] == 3) {
      Q[tim][0].push_back(q[i][1]);
      Q[tim][1].push_back(q[i][2]);
      Q[tim][2].push_back(++qcnt);
    }
  }
  for (auto i : has) {
    if (i.second) {
      update(1, 1, All, st[i.second], All, make_pair(i.first, fin[i.second]));
    }
  }
  solve(1, 1, All, ori);
  for (int i = 1; i <= qcnt; i++) {
    printf("%d\n", ans[i]);
  }
  return 0;
}
